AMQP-334 Fix Nested Cause Classification

Consider Foo caused by Bar caused by Baz.

If Bar is categorized TRUE and Baz categorized FALSE, classiy() should
return TRUE (hit on Bar), but it returned FALSE.

The early exit from the cause traversal was not taken because we
were always testing against the top level throwable (Bar).

Add a test to verify this scenario; test against the cause on
each iteration through the loop.
This commit is contained in:
Gary Russell
2013-10-02 11:17:39 -04:00
parent 6396f11878
commit aad050ba47
2 changed files with 48 additions and 1 deletions

View File

@@ -110,7 +110,7 @@ public class BinaryExceptionClassifier extends SubclassClassifier<Throwable, Boo
if (classified.equals(this.getDefault())) {
Throwable cause = classifiable;
do {
if (this.getClassified().containsKey(classifiable.getClass())) {
if (this.getClassified().containsKey(cause.getClass())) {
return classified; // non-default classification
}
cause = cause.getCause();

View File

@@ -21,9 +21,13 @@ import static org.junit.Assert.assertTrue;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import org.junit.Test;
import org.springframework.beans.DirectFieldAccessor;
public class BinaryExceptionClassifierTests {
BinaryExceptionClassifier classifier = new BinaryExceptionClassifier(false);
@@ -65,6 +69,27 @@ public class BinaryExceptionClassifierTests {
assertTrue(binaryExceptionClassifier.classify(new RuntimeException(new IllegalStateException("Foo"))));
}
@Test
public void testClassifySubclassMatchInCause() {
Collection<Class<? extends Throwable>> set = Collections
.<Class<? extends Throwable>> singleton(IllegalStateException.class);
BinaryExceptionClassifier binaryExceptionClassifier = new BinaryExceptionClassifier(set);
binaryExceptionClassifier.setTraverseCauses(true);
assertTrue(binaryExceptionClassifier.classify(new RuntimeException(new FooException("Foo"))));
}
@Test
public void testClassifySubclassMatchInCauseFalse() {
Map<Class<? extends Throwable>, Boolean> map = new HashMap<Class<? extends Throwable>, Boolean>();
map.put(IllegalStateException.class, true);
map.put(BarException.class, false);
BinaryExceptionClassifier binaryExceptionClassifier = new BinaryExceptionClassifier(map, true);
binaryExceptionClassifier.setTraverseCauses(true);
assertTrue(binaryExceptionClassifier.classify(new RuntimeException(new FooException("Foo", new BarException()))));
assertTrue(((Map<?, ?>) new DirectFieldAccessor(binaryExceptionClassifier).getPropertyValue("classified"))
.containsKey(FooException.class));
}
@Test
public void testTypesProvidedInConstructor() {
classifier = new BinaryExceptionClassifier(Collections
@@ -86,4 +111,26 @@ public class BinaryExceptionClassifierTests {
classifier.setTraverseCauses(true);
assertFalse(classifier.classify(new RuntimeException(new RuntimeException(new IllegalStateException("Foo")))));
}
@SuppressWarnings("serial")
private class FooException extends IllegalStateException {
private FooException(String s) {
super(s);
}
private FooException(String s, Throwable t) {
super(s, t);
}
}
@SuppressWarnings("serial")
private class BarException extends RuntimeException {
private BarException() {
super();
}
}
}