Skip to content

Commit

Permalink
You can now ignore throwables and not only exceptions
Browse files Browse the repository at this point in the history
  • Loading branch information
johanhaleby committed Apr 2, 2017
1 parent 11d5681 commit 69b9244
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 10 deletions.
Expand Up @@ -167,10 +167,11 @@ public <T> void await(final ConditionEvaluationHandler<T> conditionEvaluationHan
* {@inheritDoc}
*/
public void uncaughtException(Thread thread, Throwable throwable) {
// TODO Ignore exception if applicable!!!
uncaughtThrowable.set(throwable);
// We shutdown the executor "now" in order to fail the test immediately
executor.shutdownNow();
if (!conditionSettings.shouldExceptionBeIgnored(throwable)) {
uncaughtThrowable.set(throwable);
// We shutdown the executor "now" in order to fail the test immediately
executor.shutdownNow();
}
}

private class ConditionPoller implements Callable<ConditionEvaluationResult> {
Expand Down
80 changes: 74 additions & 6 deletions awaitility/src/test/java/org/awaitility/AwaitilityTest.java
Expand Up @@ -26,13 +26,18 @@
import java.util.Collections;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;

import static java.util.concurrent.TimeUnit.*;
import static org.awaitility.Awaitility.*;
import static org.awaitility.Duration.ONE_SECOND;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

public class AwaitilityTest {

Expand Down Expand Up @@ -139,13 +144,13 @@ public void foreverConditionWithHamcrestCollectionMatchersWithDirectBlock() thro
}

@Test(timeout = 3000, expected = ConditionTimeoutException.class)
public void throwsTimeoutExceptionWhenDoneEarlierThanAtLeastConstraint() throws Exception{
public void throwsTimeoutExceptionWhenDoneEarlierThanAtLeastConstraint() throws Exception {
new Asynch(fakeRepository).perform();
await().atLeast(1, SECONDS).and().atMost(2, SECONDS).until(value(), equalTo(1));
}

@Test(timeout = 3000)
public void doesNotThrowTimeoutExceptionWhenDoneLaterThanAtLeastConstraint() throws Exception{
public void doesNotThrowTimeoutExceptionWhenDoneLaterThanAtLeastConstraint() throws Exception {
new Asynch(fakeRepository).perform();
await().atLeast(100, NANOSECONDS).until(value(), equalTo(1));
}
Expand Down Expand Up @@ -179,6 +184,69 @@ public void uncaughtThrowablesArePropagatedToAwaitingThreadAndBreaksForeverBlock
await().forever().until(value(), equalTo(1));
}

@Test(timeout = 2000)
public void uncaughtThrowablesFromOtherThreadsCanBeIgnored() throws Exception {
final AtomicInteger atomicInteger = new AtomicInteger(0);
final AtomicBoolean exceptionThrown = new AtomicBoolean(false);
final ExecutorService es = Executors.newFixedThreadPool(5);
final FakeRepository fakeRepository = new FakeRepository() {

@Override
public int getValue() {
int value = atomicInteger.get();
if (value < 3) {
exceptionThrown.set(true);
throw new IllegalArgumentException("Error!");
}
return value;
}

@Override
public void setValue(int value) {

atomicInteger.set(value);
}
};
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
while (atomicInteger.get() < 3) {
try {
es.submit(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(50);
fakeRepository.setValue(atomicInteger.incrementAndGet());

} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}).get();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
});
thread.start();

try {
given().pollDelay(0, MILLISECONDS).and().ignoreExceptions().await().until(new Callable<Boolean>() {
@Override
public Boolean call() throws Exception {
return fakeRepository.getValue() == 3;
}
});
assertEquals(3, atomicInteger.get());
assertTrue(exceptionThrown.get());
} finally {
thread.join();
es.shutdownNow();
}
}

@Test(timeout = 2000, expected = IllegalStateException.class)
public void uncaughtExceptionsArePropagatedToAwaitingThreadAndBreaksForeverBlockWhenCatchingAllUncaughtExceptions()
throws Exception {
Expand Down Expand Up @@ -231,8 +299,8 @@ public void exceptionsInConditionsArePropagatedToAwaitingThreadAndBreaksForeverB
public void awaitWithAliasDisplaysAliasWhenConditionTimeoutExceptionOccurs() throws Exception {
String alias = "test";
exception.expect(ConditionTimeoutException.class);
exception.expectMessage(
"Condition with alias 'test' didn't complete within 120 milliseconds because org.awaitility.classes.FakeRepositoryValue expected a value greater than <0> but <0> was equal to <0>.");
exception.expectMessage(
"Condition with alias 'test' didn't complete within 120 milliseconds because org.awaitility.classes.FakeRepositoryValue expected a value greater than <0> but <0> was equal to <0>.");

await(alias).atMost(120, MILLISECONDS).until(value(), greaterThan(0));
}
Expand All @@ -251,10 +319,10 @@ public Boolean call() throws Exception {
}

@Test(timeout = 2000)
public void awaitDisplaysSupplierAndMatcherMismatchMessageWhenConditionTimeoutExceptionOccurs() throws Exception {
public void awaitDisplaysSupplierAndMatcherMismatchMessageWhenConditionTimeoutExceptionOccurs() throws Exception {
exception.expect(ConditionTimeoutException.class);
exception.expectMessage(FakeRepositoryValue.class.getName()
+ " expected a value greater than <0> but <0> was equal to <0> within 120 milliseconds.");
+ " expected a value greater than <0> but <0> was equal to <0> within 120 milliseconds.");

with().pollInterval(10, MILLISECONDS).then().await().atMost(120, MILLISECONDS).until(value(), greaterThan(0));
}
Expand Down
2 changes: 2 additions & 0 deletions changelog.txt
Expand Up @@ -13,6 +13,8 @@ Changelog next version
}
}).until(..);
(issue 85)
* Uncaught exceptions from other threads now takes "ignore exceptions" into account. For example if any thread throws IllegalArgumentException and this exception has been marked as ignored then it won't be treated as an error.
Previously this was only applicable to exceptions that were thrown by the polling (condition evaluation) thread.

Changelog 3.0.0-rc2 (2017-03-31)
--------------------------------
Expand Down

0 comments on commit 69b9244

Please sign in to comment.