Skip to content

Commit

Permalink
Throw an exception when during polling conditions there is an excepti…
Browse files Browse the repository at this point in the history
…on invoking the closure.

Co-authored-by: jordi9 <[email protected]>
  • Loading branch information
jsalinaspolo and jordi9 committed Apr 24, 2019
1 parent 761f88e commit 6d5e6cf
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 10 deletions.
2 changes: 1 addition & 1 deletion spock-core/src/main/java/spock/lang/Retry.java
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ enum Mode {
ITERATION,

/**
* Retry the the feature together with the setup and cleanup methods.
* Retry the feature together with the setup and cleanup methods.
*/
SETUP_FEATURE_CLEANUP
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import org.spockframework.lang.ConditionBlock;
import org.spockframework.runtime.GroovyRuntimeUtil;
import org.spockframework.runtime.SpockTimeoutError;
import org.spockframework.runtime.UnallowedExceptionThrownError;
import org.spockframework.util.Beta;

/**
Expand Down Expand Up @@ -47,6 +48,7 @@ public class PollingConditions {
private double initialDelay = 0;
private double delay = 0.1;
private double factor = 1.0;
private boolean strict = false;

/**
* Returns the timeout (in seconds) until which the conditions have to be satisfied.
Expand Down Expand Up @@ -122,11 +124,18 @@ public void setFactor(double factor) {
this.factor = factor;
}

/**
* Returns if is strict mode. If strict mode is enabled, will fail if any exception rather than {@link AssertionError} is thrown.
* Defaults to {@code false}
*/
public boolean isStrict() {
return strict;
}

/**
* Repeatedly evaluates the specified conditions until they are satisfied or the timeout has elapsed.
*
* @param conditions the conditions to evaluate
*
* @throws InterruptedException if evaluation is interrupted
*/
@ConditionBlock
Expand All @@ -138,11 +147,10 @@ public void eventually(Closure<?> conditions) throws InterruptedException {
* Repeatedly evaluates the specified conditions until they are satisfied or the specified timeout (in seconds) has elapsed.
*
* @param conditions the conditions to evaluate
*
* @throws InterruptedException if evaluation is interrupted
*/
@ConditionBlock
public void within(double seconds, Closure<?> conditions) throws InterruptedException {
public void within(double seconds, Closure<?> conditions) throws InterruptedException {
long timeoutMillis = toMillis(seconds);
long start = System.currentTimeMillis();
long lastAttempt = 0;
Expand All @@ -151,13 +159,16 @@ public void within(double seconds, Closure<?> conditions) throws InterruptedExce
long currDelay = toMillis(delay);
int attempts = 0;

while(true) {
while (true) {
try {
attempts++;
lastAttempt = System.currentTimeMillis();
GroovyRuntimeUtil.invokeClosure(conditions);
return;
} catch (Throwable e) {
if (strict && !(e instanceof AssertionError)) {
throw new UnallowedExceptionThrownError(e.getClass(), e);
}
long elapsedTime = lastAttempt - start;
if (elapsedTime >= timeoutMillis) {
String msg = String.format("Condition not satisfied after %1.2f seconds and %d attempts", elapsedTime / 1000d, attempts);
Expand Down
6 changes: 3 additions & 3 deletions spock-specs/specs.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ configurations {
}

dependencies {
testCompile project(":spock-core")
testCompile project(":spock-junit4")
testImplementation project(":spock-core")
testImplementation project(":spock-junit4")

testRuntime libs.asm
testRuntime libs.bytebuddy
Expand All @@ -30,7 +30,7 @@ targetCompatibility = javaVersion
// necessary to make @NotYetImplemented transform work (transform that ships
// with Groovy and statically references third-party class junit.framwork.AssertionFailedError)
tasks.withType(GroovyCompile) {
groovyClasspath += configurations.junit
groovyClasspath += configurations.junit
}

ext.spockLogFileDir = file("$buildDir/spock/logFiles")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ package spock.util.concurrent

import org.spockframework.runtime.ConditionNotSatisfiedError
import org.spockframework.runtime.SpockTimeoutError
import org.spockframework.runtime.UnallowedExceptionThrownError
import spock.lang.Issue
import spock.lang.Specification

Expand Down Expand Up @@ -126,12 +127,49 @@ class PollingConditionsSpec extends Specification {
then:
condition.eventually {
try {
sleep 200;
assert secondAttempt;
sleep 200
assert secondAttempt
} finally {
secondAttempt = true
}
}
}

def "fails if an exception is thrown while polling"() {
given:
def iteration = 0

when:
new PollingConditions(strict: true).eventually {
try {
if (iteration < 2) {
throw new IllegalStateException("An exception is thrown")
}
assert true
} finally {
iteration++
}
}
then:
def ex = thrown(UnallowedExceptionThrownError)
ex.unallowed == IllegalStateException
}

def "swallow intermediate exceptions while polling"() {
given:
def iteration = 0

expect:
new PollingConditions(strict: false).eventually {
try {
if (iteration < 2) {
throw new IllegalStateException("An exception is thrown")
}
assert true
} finally {
iteration++
}
}
}
}

0 comments on commit 6d5e6cf

Please sign in to comment.