Skip to content

Commit

Permalink
[polish] Improve coverage and implementation of Exceptions utils
Browse files Browse the repository at this point in the history
 - multiple(Iterable) now produces a CompositeException
 - isErrorCallbackNotImplemented simplified to instanceof
 - added various tests to improve method coverage
  • Loading branch information
simonbasle committed Nov 25, 2019
1 parent 38b8669 commit 635ca1a
Show file tree
Hide file tree
Showing 2 changed files with 165 additions and 8 deletions.
4 changes: 2 additions & 2 deletions reactor-core/src/main/java/reactor/core/Exceptions.java
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ public static RuntimeException multiple(Throwable... throwables) {
* @see #addThrowable(AtomicReferenceFieldUpdater, Object, Throwable)
*/
public static RuntimeException multiple(Iterable<Throwable> throwables) {
RuntimeException multiple = new RuntimeException("Multiple exceptions");
CompositeException multiple = new CompositeException();
//noinspection ConstantConditions
if (throwables != null) {
for (Throwable t : throwables) {
Expand Down Expand Up @@ -285,7 +285,7 @@ public static boolean isCancel(@Nullable Throwable t) {
* @return true if given {@link Throwable} is a callback not implemented exception.
*/
public static boolean isErrorCallbackNotImplemented(@Nullable Throwable t) {
return t != null && t.getClass().equals(ErrorCallbackNotImplemented.class);
return t instanceof ErrorCallbackNotImplemented;
}

/**
Expand Down
169 changes: 163 additions & 6 deletions reactor-core/src/test/java/reactor/core/ExceptionsTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,27 +16,27 @@
package reactor.core;

import java.io.IOException;
import java.util.Arrays;
import java.util.Collections;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;

import org.junit.Before;
import org.junit.Test;
import reactor.test.util.RaceTestUtils;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.*;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static reactor.core.Exceptions.NOT_TIME_CAPABLE_REJECTED_EXECUTION;
import static reactor.core.Exceptions.REJECTED_EXECUTION;
import static reactor.core.Exceptions.TERMINATED;
import static reactor.core.Exceptions.*;

/**
* @author Stephane Maldini
*/
public class ExceptionsTest {

@Test
public void testWrapping() throws Exception {
public void bubble() throws Exception {

Throwable t = new Exception("test");

Expand All @@ -46,13 +46,46 @@ public void testWrapping() throws Exception {
}

@Test
public void testNullWrapping() throws Exception {
public void nullBubble() throws Exception {

Throwable w = Exceptions.bubble(null);

assertTrue(Exceptions.unwrap(w) == w);
}

@Test
public void duplicateOnSubscribeReferencesSpec() {
IllegalStateException error = duplicateOnSubscribeException();
assertThat(error).hasMessageContaining("Rule 2.12");
}

@Test
public void duplicateOnSubscribeCreatesNewInstances() {
IllegalStateException error1 = duplicateOnSubscribeException();
IllegalStateException error2 = duplicateOnSubscribeException();

assertThat(error1).isNotSameAs(error2);
}

@Test
public void errorCallbackNotImplementedRejectsNull() {
//noinspection ThrowableNotThrown,ConstantConditions
assertThatNullPointerException().isThrownBy(() -> Exceptions.errorCallbackNotImplemented(null));
}

@Test
public void isErrorCallbackNotImplemented() {
UnsupportedOperationException vanillaUnsupported = new UnsupportedOperationException("not error callback");
UnsupportedOperationException t = errorCallbackNotImplemented(new IllegalStateException("in error callback"));

assertThat(Exceptions.isErrorCallbackNotImplemented(vanillaUnsupported))
.as("not error callback")
.isFalse();
assertThat(Exceptions.isErrorCallbackNotImplemented(t))
.as("error callback")
.isTrue();
}

@Test
public void allOverflowIsIllegalState() {
IllegalStateException overflow1 = Exceptions.failWithOverflow();
Expand All @@ -69,11 +102,101 @@ public void allIllegalStateIsntOverflow() {
assertFalse(Exceptions.isOverflow(ise));
}

@Test
public void failWithRejectedIsSingleton() {
assertThat(Exceptions.failWithRejected())
.isSameAs(Exceptions.failWithRejected())
.isNotSameAs(Exceptions.failWithRejectedNotTimeCapable());
}

@Test
public void failWithRejectedNotTimeCapableIsSingleton() {
assertThat(Exceptions.failWithRejectedNotTimeCapable())
.isSameAs(Exceptions.failWithRejectedNotTimeCapable())
.isNotSameAs(Exceptions.failWithRejected());
}

@Test
public void isBubbling() {
Throwable notBubbling = new ReactiveException("foo");
Throwable bubbling = new BubblingException("foo");

assertThat(Exceptions.isBubbling(notBubbling)).as("not bubbling").isFalse();
assertThat(Exceptions.isBubbling(bubbling)).as("bubbling").isTrue();
}

@Test
public void isCancelAndCancelIsBubbling() {
Throwable notCancel = new BubblingException("foo");
Throwable cancel = new CancelException();

assertThat(Exceptions.isCancel(notCancel)).as("not cancel").isFalse();
assertThat(Exceptions.isCancel(cancel)).as("cancel").isTrue();

assertThat(Exceptions.isBubbling(cancel)).as("cancel are bubbling").isTrue();
}

@Test
public void nullOrNegativeRequestReferencesSpec() {
assertThat(Exceptions.nullOrNegativeRequestException(-3))
.hasMessage("Spec. Rule 3.9 - Cannot request a non strictly positive number: -3");
}

@Test
public void propagateDoesntWrapRuntimeException() {
Throwable t = new RuntimeException("expected");
assertThat(Exceptions.propagate(t)).isSameAs(t);
}

//TODO test terminate

@Test
public void throwIfFatalThrowsBubbling() {
BubblingException expected = new BubblingException("expected");

assertThatExceptionOfType(BubblingException.class)
.isThrownBy(() -> Exceptions.throwIfFatal(expected))
.isSameAs(expected);
}

@Test
public void throwIfFatalThrowsErrorCallbackNotImplemented() {
ErrorCallbackNotImplemented expected = new ErrorCallbackNotImplemented(new IllegalStateException("expected cause"));

assertThatExceptionOfType(ErrorCallbackNotImplemented.class)
.isThrownBy(() -> Exceptions.throwIfFatal(expected))
.isSameAs(expected)
.withCause(expected.getCause());
}

@Test
public void throwIfJvmFatal() {
VirtualMachineError fatal1 = new VirtualMachineError() {};
ThreadDeath fatal2 = new ThreadDeath();
LinkageError fatal3 = new LinkageError();

assertThatExceptionOfType(VirtualMachineError.class)
.as("VirtualMachineError")
.isThrownBy(() -> Exceptions.throwIfJvmFatal(fatal1))
.isSameAs(fatal1);

assertThatExceptionOfType(ThreadDeath.class)
.as("ThreadDeath")
.isThrownBy(() -> Exceptions.throwIfJvmFatal(fatal2))
.isSameAs(fatal2);

assertThatExceptionOfType(LinkageError.class)
.as("LinkageError")
.isThrownBy(() -> Exceptions.throwIfJvmFatal(fatal3))
.isSameAs(fatal3);
}

@Test
public void multipleWithNullVararg() {
//noinspection ConstantConditions
assertThat(Exceptions.multiple((Throwable[]) null))
.isInstanceOf(RuntimeException.class)
.isExactlyInstanceOf(CompositeException.class)
.hasMessage("Multiple exceptions")
.hasNoSuppressedExceptions();
}
Expand All @@ -84,6 +207,7 @@ public void multipleWithOneVararg() {

assertThat(Exceptions.multiple(e1))
.isInstanceOf(RuntimeException.class)
.isExactlyInstanceOf(CompositeException.class)
.hasMessage("Multiple exceptions")
.hasSuppressedException(e1);
}
Expand All @@ -95,6 +219,39 @@ public void multipleWithTwoVararg() {

assertThat(Exceptions.multiple(e1, e2))
.isInstanceOf(RuntimeException.class)
.isExactlyInstanceOf(CompositeException.class)
.hasMessage("Multiple exceptions")
.hasSuppressedException(e1)
.hasSuppressedException(e2);
}

@Test
public void multipleWithNullIterable() {
//noinspection ConstantConditions
assertThat(Exceptions.multiple((Iterable<Throwable>) null))
.isInstanceOf(RuntimeException.class)
.isExactlyInstanceOf(CompositeException.class)
.hasMessage("Multiple exceptions")
.hasNoSuppressedExceptions();
}

@Test
public void multipleWithEmptyIterable() {
assertThat(Exceptions.multiple(Collections.emptyList()))
.isInstanceOf(RuntimeException.class)
.isExactlyInstanceOf(CompositeException.class)
.hasMessage("Multiple exceptions")
.hasNoSuppressedExceptions();
}

@Test
public void multipleWithIterable() {
IOException e1 = new IOException("boom");
IllegalArgumentException e2 = new IllegalArgumentException("boom");

assertThat(Exceptions.multiple(Arrays.asList(e1, e2)))
.isInstanceOf(RuntimeException.class)
.isExactlyInstanceOf(CompositeException.class)
.hasMessage("Multiple exceptions")
.hasSuppressedException(e1)
.hasSuppressedException(e2);
Expand Down

0 comments on commit 635ca1a

Please sign in to comment.