/** * Copyright 2014 Netflix, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package rx.exceptions; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import java.io.ByteArrayOutputStream; import java.io.PrintStream; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import org.junit.Test; public class CompositeExceptionTest { private final Throwable ex1 = new Throwable("Ex1"); private final Throwable ex2 = new Throwable("Ex2", ex1); private final Throwable ex3 = new Throwable("Ex3", ex2); public CompositeExceptionTest() { } private CompositeException getNewCompositeExceptionWithEx123() { List<Throwable> throwables = new ArrayList<Throwable>(); throwables.add(ex1); throwables.add(ex2); throwables.add(ex3); return new CompositeException(throwables); } @Test(timeout = 1000) public void testMultipleWithSameCause() { Throwable rootCause = new Throwable("RootCause"); Throwable e1 = new Throwable("1", rootCause); Throwable e2 = new Throwable("2", rootCause); Throwable e3 = new Throwable("3", rootCause); CompositeException ce = new CompositeException("3 failures with same root cause", Arrays.asList(e1, e2, e3)); System.err.println("----------------------------- print composite stacktrace"); ce.printStackTrace(); assertEquals(3, ce.getExceptions().size()); assertNoCircularReferences(ce); assertNotNull(getRootCause(ce)); System.err.println("----------------------------- print cause stacktrace"); ce.getCause().printStackTrace(); } @Test(timeout = 1000) public void testCompositeExceptionFromParentThenChild() { CompositeException cex = new CompositeException(Arrays.asList(ex1, ex2)); System.err.println("----------------------------- print composite stacktrace"); cex.printStackTrace(); assertEquals(2, cex.getExceptions().size()); assertNoCircularReferences(cex); assertNotNull(getRootCause(cex)); System.err.println("----------------------------- print cause stacktrace"); cex.getCause().printStackTrace(); } @Test(timeout = 1000) public void testCompositeExceptionFromChildThenParent() { CompositeException cex = new CompositeException(Arrays.asList(ex2, ex1)); System.err.println("----------------------------- print composite stacktrace"); cex.printStackTrace(); assertEquals(2, cex.getExceptions().size()); assertNoCircularReferences(cex); assertNotNull(getRootCause(cex)); System.err.println("----------------------------- print cause stacktrace"); cex.getCause().printStackTrace(); } @Test(timeout = 1000) public void testCompositeExceptionFromChildAndComposite() { CompositeException cex = new CompositeException(Arrays.asList(ex1, getNewCompositeExceptionWithEx123())); System.err.println("----------------------------- print composite stacktrace"); cex.printStackTrace(); assertEquals(3, cex.getExceptions().size()); assertNoCircularReferences(cex); assertNotNull(getRootCause(cex)); System.err.println("----------------------------- print cause stacktrace"); cex.getCause().printStackTrace(); } @Test(timeout = 1000) public void testCompositeExceptionFromCompositeAndChild() { CompositeException cex = new CompositeException(Arrays.asList(getNewCompositeExceptionWithEx123(), ex1)); System.err.println("----------------------------- print composite stacktrace"); cex.printStackTrace(); assertEquals(3, cex.getExceptions().size()); assertNoCircularReferences(cex); assertNotNull(getRootCause(cex)); System.err.println("----------------------------- print cause stacktrace"); cex.getCause().printStackTrace(); } @Test(timeout = 1000) public void testCompositeExceptionFromTwoDuplicateComposites() { List<Throwable> exs = new ArrayList<Throwable>(); exs.add(getNewCompositeExceptionWithEx123()); exs.add(getNewCompositeExceptionWithEx123()); CompositeException cex = new CompositeException(exs); System.err.println("----------------------------- print composite stacktrace"); cex.printStackTrace(); assertEquals(3, cex.getExceptions().size()); assertNoCircularReferences(cex); assertNotNull(getRootCause(cex)); System.err.println("----------------------------- print cause stacktrace"); cex.getCause().printStackTrace(); } /** * This hijacks the Throwable.printStackTrace() output and puts it in a string, where we can look for * "CIRCULAR REFERENCE" (a String added by Throwable.printEnclosedStackTrace) */ private static void assertNoCircularReferences(Throwable ex) { ByteArrayOutputStream baos = new ByteArrayOutputStream(); PrintStream printStream = new PrintStream(baos); ex.printStackTrace(printStream); assertFalse(baos.toString().contains("CIRCULAR REFERENCE")); } private static Throwable getRootCause(Throwable ex) { Throwable root = ex.getCause(); if (root == null) { return null; } else { while(true) { if (root.getCause() == null) { return root; } else { root = root.getCause(); } } } } }