1 import static org.testng.Assert.assertTrue;
   2 import static org.testng.Assert.assertEquals;
   3 
   4 import org.testng.annotations.Test;
   5 
   6 import java.io.PrintWriter;
   7 import java.io.StringWriter;
   8 
   9 /*
  10  * @test
  11  * @bug 5050783
  12  * @summary Basic test presenting of stack trace information as String
  13  * @author Bulgarian JUG
  14  * @run testng GetStackTraceString
  15  */
  16 public class GetStackTraceString {
  17     private Throwable rootCause = createThrowable("Root Cause Message");
  18     private Throwable wrapperFailure = createThrowable("Wrapper Message", rootCause);
  19     private Throwable unwritableRootCause = createUnwritableThrowable("Unwritable Root", null);
  20     private Throwable unwritableWrapper = createUnwritableThrowable("Unwritable Wrapper", unwritableRootCause);
  21 
  22     @Test
  23     public void testRootCauseHeaderLine() {
  24         assertContains(getHeaderLine(rootCause), rootCause.getMessage());
  25     }
  26 
  27     @Test
  28     public void testWrapperHeaderLine() {
  29         assertContains(getHeaderLine(wrapperFailure), wrapperFailure.getMessage());
  30     }
  31 
  32     @Test
  33     public void wrapperContainsCause() {
  34         assertContains(getCauseLine(wrapperFailure), rootCause.getMessage());
  35     }
  36 
  37     @Test
  38     public void unwritableWrapperContainsCause() {
  39         assertContains(getCauseLine(unwritableWrapper), unwritableRootCause.getMessage());
  40     }
  41 
  42     @Test
  43     public void secondLineShouldContainFactoryCall() {
  44         assertContains(getLines(rootCause)[1],
  45                 String.format("\tat %s.createThrowable", getClass().getName()));
  46     }
  47 
  48     @Test
  49     public void unwritableRootCauseHasHeaderOnly() {
  50         assertEquals(getLines(unwritableRootCause).length, 1, String.format(
  51                 "Actual stack trace:'%n%s'", unwritableRootCause.getStackTraceString()));
  52     }
  53 
  54     @Test
  55     public void printStackTraceComparissonTest() {
  56         StringWriter sw = new StringWriter();
  57         wrapperFailure.printStackTrace(new PrintWriter(sw));
  58         assertEquals(sw.toString(), wrapperFailure.getStackTraceString());
  59     }
  60 
  61     /*--- Assert helpers ---*/
  62     private void assertContains(String actual, String expectedSubstring) {
  63         assertTrue(actual.contains(expectedSubstring), String.format(
  64                 "Mismatch: expected to contain%n'%s'%nActual:%n'%s'%n",
  65                 expectedSubstring, actual));
  66     }
  67 
  68     /*--- Access helpers ---*/
  69 
  70     private String[] getLines(Throwable t) {
  71         return t.getStackTraceString().split(System.lineSeparator());
  72     }
  73 
  74     private String getHeaderLine(Throwable t) {
  75         return getLines(t)[0];
  76     }
  77 
  78     private String getCauseLine(Throwable t) {
  79         return java.util.Arrays.stream(getLines(t))
  80             .filter(s -> s.startsWith("Caused by:")).findFirst().orElse("");
  81     }
  82 
  83     /*--- Factory helpers ---*/
  84     private Throwable createThrowable(String message) {
  85         return createThrowable(message, null, true, true);
  86     }
  87 
  88     private Throwable createThrowable(String message, Throwable cause) {
  89         return createThrowable(message, cause, true, true);
  90     }
  91 
  92     private Throwable createUnwritableThrowable(String message, Throwable cause) {
  93         return createThrowable(message, cause, true, false);
  94     }
  95 
  96     private Throwable createThrowable(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
  97         return new MyThrowable(message, cause, enableSuppression, writableStackTrace);
  98     }
  99 
 100     private static class MyThrowable extends Throwable {
 101         MyThrowable(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
 102             super(message, cause, enableSuppression, writableStackTrace);
 103         }
 104     }
 105 }