Skip to content

Commit

Permalink
Make parallel extensions support inheritance
Browse files Browse the repository at this point in the history
fixes #1245
  • Loading branch information
leonard84 committed Jan 4, 2021
1 parent c1e098d commit 14f4ad5
Show file tree
Hide file tree
Showing 5 changed files with 219 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
public class ExecutionExtension implements IAnnotationDrivenExtension<Execution> {
@Override
public void visitSpecAnnotation(Execution annotation, SpecInfo spec) {
spec.setExecutionMode(annotation.value());
spec.getBottomSpec().setExecutionMode(annotation.value());
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,6 @@ public class IsolatedExtension implements IAnnotationDrivenExtension<Isolated> {

@Override
public void visitSpecAnnotations(List<Isolated> annotations, SpecInfo spec) {
spec.addExclusiveResource(GLOBAL_LOCK);
spec.getBottomSpec().addExclusiveResource(GLOBAL_LOCK);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import java.util.List;

import org.spockframework.runtime.extension.IAnnotationDrivenExtension;
import org.spockframework.runtime.model.FeatureInfo;
import org.spockframework.runtime.model.SpecInfo;
import org.spockframework.runtime.model.parallel.ExclusiveResource;

Expand All @@ -12,10 +13,11 @@ public class ResourceLockChildrenExtension implements IAnnotationDrivenExtension

@Override
public void visitSpecAnnotations(List<ResourceLockChildren> annotations, SpecInfo spec) {
List<FeatureInfo> allFeatures = spec.getBottomSpec().getAllFeatures();
annotations.stream()
.map(this::toExclusiveResource)
.forEach(lockResource ->
spec.getFeatures().forEach(feature -> feature.addExclusiveResource(lockResource)));
allFeatures.forEach(feature -> feature.addExclusiveResource(lockResource)));
}

private ExclusiveResource toExclusiveResource(ResourceLockChildren lockResource) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public void visitFeatureAnnotations(List<ResourceLock> annotations, FeatureInfo

@Override
public void visitSpecAnnotations(List<ResourceLock> annotations, SpecInfo spec) {
annotations.forEach( lockResource -> spec.addExclusiveResource(
annotations.forEach( lockResource -> spec.getBottomSpec().addExclusiveResource(
toExclusiveResource(lockResource)));
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package org.spockframework.smoke.extension

import java.util.stream.Collectors

import org.spockframework.EmbeddedSpecification
import org.spockframework.runtime.model.parallel.*
import spock.lang.*
Expand Down Expand Up @@ -101,8 +103,6 @@ class ParallelSpec extends EmbeddedSpecification {
@ResourceLock("a")
def writeB() {
given: "delay a bit so that the reads don't pick up the already increased value"
sleep(20)
expect: incrementBlockAndCheck(atomicInteger, latch)
}
Expand Down Expand Up @@ -153,7 +153,46 @@ class ParallelSpec extends EmbeddedSpecification {
result.testsSucceededCount == 2
}

def "ResourceLockChildren allows parallel execution"() {
def "@ResourceLock on specs is inherited"() {
when:
def result = runner.runWithImports '''
@ResourceLock(value = "a", mode = ResourceAccessMode.READ)
abstract class BaseSpec extends Specification {
@Shared
AtomicInteger atomicInteger = new AtomicInteger()
@Shared
CountDownLatch latch = new CountDownLatch(2)
@Shared
String threadName
}
class ASpec extends BaseSpec {
def setupSpec() {
threadName = Thread.currentThread().name
}
def writeA() {
expect:
threadName == Thread.currentThread().name
incrementBlockAndCheck(atomicInteger, latch)
}
def writeB() {
expect:
threadName == Thread.currentThread().name
incrementBlockAndCheck(atomicInteger, latch)
}
}
'''

then:
result.testsSucceededCount == 2
}

def "@ResourceLockChildren allows parallel execution"() {
when:
def result = runner.runWithImports '''
@ResourceLockChildren(value = "a", mode = ResourceAccessMode.READ)
Expand All @@ -165,26 +204,88 @@ class ParallelSpec extends EmbeddedSpecification {
CountDownLatch latch = new CountDownLatch(2)
def writeA() {
when:
incrementAndBlock(atomicInteger, latch)
when:
incrementAndBlock(atomicInteger, latch)
then:
atomicInteger.get() == 2
}
then:
atomicInteger.get() == 2
def writeB() {
when:
incrementAndBlock(atomicInteger, latch)
then:
atomicInteger.get() == 2
}
}
'''

then:
result.testsSucceededCount == 2
}

def "@ResourceLockChildren can be combined with @ResourceLock"() {
when:
def result = runner.runWithImports '''
@ResourceLockChildren(value = "a", mode = ResourceAccessMode.READ)
class ASpec extends Specification {
@Shared
AtomicInteger atomicInteger = new AtomicInteger()
@Shared
CountDownLatch latch = new CountDownLatch(2)
def readA() {
expect: storeAndBlockAndCheck(atomicInteger, latch)
}
@ResourceLock("a")
def writeB() {
when:
incrementAndBlock(atomicInteger, latch)
expect: incrementBlockAndCheck(atomicInteger, latch)
}
def readC() {
expect: storeAndBlockAndCheck(atomicInteger, latch)
}
}
'''

then:
atomicInteger.get() == 2
then:
result.testsSucceededCount == 3
}
def "@ResourceLockChildren can be inherited"() {
when:
def result = runner.runWithImports '''
@ResourceLockChildren(value = "a", mode = ResourceAccessMode.READ)
abstract class BaseSpec extends Specification {
@Shared
AtomicInteger atomicInteger = new AtomicInteger()
@Shared
CountDownLatch latch = new CountDownLatch(2)
}
class ASpec extends BaseSpec {
def readA() {
expect: storeAndBlockAndCheck(atomicInteger, latch)
}
@ResourceLock("a")
def writeB() {
expect: incrementBlockAndCheck(atomicInteger, latch)
}
def readC() {
expect: storeAndBlockAndCheck(atomicInteger, latch)
}
}
'''

then:
result.testsSucceededCount == 2
result.testsSucceededCount == 3
}

def "Execution can be set to same thread execution"() {
when:
def result = runner.runWithImports '''
Expand Down Expand Up @@ -221,7 +322,46 @@ class ParallelSpec extends EmbeddedSpecification {
result.testsSucceededCount == 2
}

def "Execution can be set isolated"() {
def "@Execution on specs is inherited"() {
when:
def result = runner.runWithImports '''
@Execution(ExecutionMode.SAME_THREAD)
abstract class BaseSpec extends Specification {
@Shared
AtomicInteger atomicInteger = new AtomicInteger()
@Shared
CountDownLatch latch = new CountDownLatch(2)
@Shared
String threadName
}
class ASpec extends BaseSpec {
def setupSpec() {
threadName = Thread.currentThread().name
}
def writeA() {
expect:
threadName == Thread.currentThread().name
incrementBlockAndCheck(atomicInteger, latch)
}
def writeB() {
expect:
threadName == Thread.currentThread().name
incrementBlockAndCheck(atomicInteger, latch)
}
}
'''

then:
result.testsSucceededCount == 2
}

def "Execution can be isolated"() {
when:
def result = runner.runWithImports '''
class ASpec extends Specification {
Expand Down Expand Up @@ -280,6 +420,66 @@ class ParallelSpec extends EmbeddedSpecification {
then:
result.testsSucceededCount == 6
}
def "@Isolated is inherited"() {
when:
def result = runner.runWithImports '''
class ASpec extends Specification {
static AtomicInteger atomicInteger = new AtomicInteger()
static CountDownLatch latch = new CountDownLatch(6)
def writeA() {
expect:
storeAndBlockAndCheck(atomicInteger, latch)
}
def writeB() {
expect:
storeAndBlockAndCheck(atomicInteger, latch)
}
}
@Isolated
abstract class BaseSpec extends Specification {
@Shared
String threadName
}
class BSpec extends BaseSpec {
def setupSpec() {
threadName = Thread.currentThread().name
}
def writeA() {
expect:
threadName == Thread.currentThread().name
incrementBlockAndCheck(ASpec.atomicInteger, ASpec.latch)
}
def writeB() {
expect:
threadName == Thread.currentThread().name
incrementBlockAndCheck(ASpec.atomicInteger, ASpec.latch)
}
}
class CSpec extends Specification {
def writeA() {
expect:
storeAndBlockAndCheck(ASpec.atomicInteger, ASpec.latch)
}
def writeB() {
expect:
storeAndBlockAndCheck(ASpec.atomicInteger, ASpec.latch)
}
}
'''

then:
result.testsSucceededCount == 6
}

static void incrementBlockAndCheck(AtomicInteger sharedResource, CountDownLatch countDownLatch)
throws InterruptedException {
Expand Down

0 comments on commit 14f4ad5

Please sign in to comment.