1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    * 
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   * 
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.lang.exception;
18  
19  import java.io.ByteArrayOutputStream;
20  import java.io.EOFException;
21  import java.io.IOException;
22  import java.io.PrintStream;
23  import java.io.PrintWriter;
24  
25  import junit.framework.Test;
26  import junit.framework.TestSuite;
27  import junit.textui.TestRunner;
28  
29  /**
30   * Tests the org.apache.commons.lang.exception.NestableDelegate class.
31   *
32   * @author <a href="mailto:steven@caswell.name">Steven Caswell</a>
33   * @author Daniel L. Rall
34   * @version $Id: NestableDelegateTestCase.java 610452 2008-01-09 16:53:06Z sebb $
35   */
36  public class NestableDelegateTestCase extends junit.framework.TestCase {
37      private static final String CONSTRUCTOR_FAILED_MSG = 
38      "The Nestable implementation passed to the NestableDelegate(Nestable) constructor must extend java.lang.Throwable";
39  
40      private static final String PARTIAL_STACK_TRACE =
41          "ThrowableNestedNestable partial stack trace place-holder";
42  
43      protected String lineSeparator;
44  
45      /**
46       * Construct a new instance of NestableDelegateTestCase with the specified name
47       */
48      public NestableDelegateTestCase(String name)
49      {
50          super(name);
51      }
52  
53      /**
54       * Set up instance variables required by this test case.
55       */
56      public void setUp()
57      {
58          lineSeparator = System.getProperty("line.separator");
59      }
60      
61      public static Test suite()
62      {
63          return new TestSuite(NestableDelegateTestCase.class);
64      }
65      
66      /**
67       * Tear down instance variables required by this test case.
68       */
69      public void tearDown()
70      {
71          lineSeparator = null;
72      }
73      
74      /**
75       * Test the implementation
76       */
77      public void testNestableDelegateConstructor()
78      {
79          String msg = null;
80          boolean constructorFailed = false;
81          try
82          {
83              NestableDelegate nonThrowableCause = new NestableDelegate(new NonThrowableNestable());
84          }
85          catch(IllegalArgumentException iae)
86          {
87              constructorFailed = true;
88              msg = iae.getMessage();
89          }
90          assertTrue("nestable delegate constructor with non-throwable cause failed == true", constructorFailed);
91          assertTrue("constructor failed exception msg == " + CONSTRUCTOR_FAILED_MSG,
92              msg.equals(CONSTRUCTOR_FAILED_MSG));
93  
94          constructorFailed = false;
95          try
96          {
97              NestableDelegate nd1 = new NestableDelegate(new ThrowableNestable());
98          }
99          catch(IllegalArgumentException iae)
100         {
101             constructorFailed = true;
102         }
103         assertTrue("nestable delegate constructor with throwable cause failed == false", !constructorFailed);
104     }
105 
106     public void testNestableDelegateGetMessage()
107     {
108         Nestable ne1 = new ThrowableNestable();
109         assertTrue("ThrowableNestable ne1 getMessage() == ThrowableNestable exception",
110             ne1.getMessage().equals("ThrowableNestable exception"));
111         NestableDelegate nd1 = new NestableDelegate(ne1);
112         assertTrue("nd1 getMessage() == " + ne1.getCause().getMessage(),
113             nd1.getMessage("base").equals("base: " + ne1.getCause().getMessage()));
114         
115         Nestable ne2 = new ThrowableNestedNestable(new Exception("nested exception 2"));
116         NestableDelegate nd2 = new NestableDelegate(ne2);
117         assertTrue("nd2 getMessage() == base: " + ne2.getCause().getMessage(),
118             nd2.getMessage("base").equals("base: " + ne2.getCause().getMessage()));
119     }
120 
121     public void testNestableDelegateGetThrowableCount()
122     {
123         Nestable n = null;
124         NestableDelegate d = null;
125         
126         n = new NestableDelegateTester1();
127         d = new NestableDelegate(n);
128         doNestableDelegateGetThrowableCount(d, 1);
129         
130         n = new NestableDelegateTester1("level 1");
131         d = new NestableDelegate(n);
132         doNestableDelegateGetThrowableCount(d, 1);
133         
134         n = new NestableDelegateTester1(new Exception());
135         d = new NestableDelegate(n);
136         doNestableDelegateGetThrowableCount(d, 2);
137         
138         n = new NestableDelegateTester1(new Exception("level 2"));
139         d = new NestableDelegate(n);
140         doNestableDelegateGetThrowableCount(d, 2);
141         
142         n = new NestableDelegateTester1("level 1", 
143                 new NestableDelegateTester2("level 2", 
144                     new NestableDelegateTester1(
145                         new NestableDelegateTester2("level 4", 
146                             new Exception("level 5")
147                         )
148                     )
149                 )
150             );
151         d = new NestableDelegate(n);
152         doNestableDelegateGetThrowableCount(d, 5);
153     }
154 
155     private void doNestableDelegateGetThrowableCount(NestableDelegate d, int len)
156     {
157         // Compare the lengths
158         assertEquals("delegate length", len, d.getThrowableCount());
159     }
160     
161     public void testNestableDelegateGetMessages()
162     {
163         Nestable n = null;
164         NestableDelegate d = null;
165         String msgs[] = null;
166         
167         msgs = new String[1];
168         n = new NestableDelegateTester1();
169         d = new NestableDelegate(n);        
170         doNestableDelegateGetMessages(d, msgs);
171         
172         msgs = new String[1];
173         msgs[0] = "level 1";
174         n = new NestableDelegateTester1(msgs[0]);
175         d = new NestableDelegate(n);
176         doNestableDelegateGetMessages(d, msgs);
177 
178         msgs = new String[2];
179         n = new NestableDelegateTester1(new Exception());
180         d = new NestableDelegate(n);
181         doNestableDelegateGetMessages(d, msgs);
182 
183         msgs = new String[2];
184         msgs[0] = null;
185         msgs[1] = "level 2";
186         n = new NestableDelegateTester1(new Exception(msgs[1]));
187         d = new NestableDelegate(n);
188         doNestableDelegateGetMessages(d, msgs);
189  
190         msgs = new String[5];
191         msgs[0] = "level 1";
192         msgs[1] = "level 2";
193         msgs[2] = null;
194         msgs[3] = "level 4";
195         msgs[4] = "level 5";
196         n = new NestableDelegateTester1(msgs[0], 
197                 new NestableDelegateTester2(msgs[1], 
198                     new NestableDelegateTester1(
199                         new NestableDelegateTester2(msgs[3], 
200                             new Exception(msgs[4])
201                         )
202                     )
203                 )
204             );
205         d = new NestableDelegate(n);
206         doNestableDelegateGetMessages(d, msgs);
207     }
208 
209     private void doNestableDelegateGetMessages(NestableDelegate d, String[] nMsgs)
210     {
211         // Compare the messages
212         String[] dMsgs = d.getMessages();
213         assertEquals("messages length", nMsgs.length, dMsgs.length);
214         for(int i = 0; i < nMsgs.length; i++)
215         {
216             assertEquals("message " + i, nMsgs[i], dMsgs[i]);
217         }
218     }
219     
220     public void testGetMessageString()
221     {
222         NestableDelegateTester1 ndt1 = new NestableDelegateTester1 (new NullPointerException ());
223         NestableDelegate nd = new NestableDelegate (ndt1);
224         assertNull (nd.getMessage((String)null));
225         
226         ndt1 = new NestableDelegateTester1 (new NullPointerException ("null pointer"));
227         nd = new NestableDelegate (ndt1);
228         assertNotNull(nd.getMessage((String)null));
229         
230         ndt1 = new NestableDelegateTester1 ();
231         nd = new NestableDelegate (ndt1);
232         assertNull(nd.getMessage((String)null));
233         
234         ndt1 = new NestableDelegateTester1 ("root");
235         nd = new NestableDelegate (ndt1);
236         assertNull(nd.getMessage((String)null));
237     }
238 
239     public void testNestableDelegateGetMessageN()
240     {
241         Nestable n = null;
242         NestableDelegate d = null;
243         String[] msgs = new String[5];
244         msgs[0] = "level 1";
245         msgs[1] = "level 2";
246         msgs[2] = null;
247         msgs[3] = "level 4";
248         msgs[4] = "level 5";
249         n = new NestableDelegateTester1(msgs[0], 
250                 new NestableDelegateTester2(msgs[1], 
251                     new NestableDelegateTester1(
252                         new NestableDelegateTester2(msgs[3], 
253                             new Exception(msgs[4])
254                         )
255                     )
256                 )
257             );
258         d = new NestableDelegate(n);
259         for(int i = 0; i < msgs.length; i++)
260         {
261             assertEquals("message " + i, msgs[i], d.getMessage(i));
262         }
263         
264         // Test for index out of bounds
265         try
266         {
267             String msg = d.getMessage(-1);
268             fail("getMessage(-1) should have thrown IndexOutOfBoundsException");
269         }
270         catch(IndexOutOfBoundsException ioode)
271         {
272         }
273         try
274         {
275             String msg = d.getMessage(msgs.length + 100);
276             fail("getMessage(999) should have thrown IndexOutOfBoundsException");
277         }
278         catch(IndexOutOfBoundsException ioode)
279         {
280         }
281     }
282 
283     public void testNestableDelegateGetThrowableN()
284     {
285         Nestable n = null;
286         NestableDelegate d = null;
287         String msgs[] = null;
288         Class[] throwables = null;
289         
290         msgs = new String[2];
291         msgs[0] = null;
292         msgs[1] = "level 2";
293         throwables = new Class[2];
294         throwables[0] = NestableDelegateTester1.class;
295         throwables[1] = Exception.class;
296         n = new NestableDelegateTester1(new Exception(msgs[1]));
297         d = new NestableDelegate(n);
298         doNestableDelegateGetThrowableN(d, throwables, msgs);
299  
300         msgs = new String[5];
301         msgs[0] = "level 1";
302         msgs[1] = "level 2";
303         msgs[2] = null;
304         msgs[3] = "level 4";
305         msgs[4] = "level 5";
306         throwables = new Class[5];
307         throwables[0] = NestableDelegateTester1.class;
308         throwables[1] = NestableDelegateTester2.class;
309         throwables[2] = NestableDelegateTester1.class;
310         throwables[3] = NestableDelegateTester2.class;
311         throwables[4] = Exception.class;        
312         n = new NestableDelegateTester1(msgs[0], 
313                 new NestableDelegateTester2(msgs[1], 
314                     new NestableDelegateTester1(
315                         new NestableDelegateTester2(msgs[3], 
316                             new Exception(msgs[4])
317                             )
318                         )
319                     )
320                 );
321         d = new NestableDelegate(n);
322         doNestableDelegateGetThrowableN(d, throwables, msgs);
323     }
324 
325     private void doNestableDelegateGetThrowableN(NestableDelegate d, Class[] classes, String[] msgs)
326     {
327         Throwable t = null;
328         String msg = null;
329         
330         for(int i = 0; i < classes.length; i++)
331         {
332             t = d.getThrowable(i);
333             assertEquals("throwable class", classes[i], t.getClass());
334             if(Nestable.class.isInstance(t))
335             {
336                 msg = ((Nestable) t).getMessage(0);
337             }
338             else
339             {
340                 msg = t.getMessage();
341             }
342             assertEquals("throwable message", msgs[i], msg);
343         }
344         
345         // Test for index out of bounds
346         try
347         {
348             t = d.getThrowable(-1);
349             fail("getThrowable(-1) should have thrown IndexOutOfBoundsException");
350         }
351         catch(IndexOutOfBoundsException ioobe)
352         {
353         }
354         try
355         {
356             t = d.getThrowable(999);
357             fail("getThrowable(999) should have thrown IndexOutOfBoundsException");
358         }
359         catch(IndexOutOfBoundsException ioobe)
360         {
361         }
362     }
363 
364     public void testNestableDelegateGetThrowables()
365     {
366         Nestable n = null;
367         NestableDelegate d = null;
368         String msgs[] = null;
369         Class[] throwables = null;
370         
371         msgs = new String[2];
372         msgs[0] = null;
373         msgs[1] = "level 2";
374         throwables = new Class[2];
375         throwables[0] = NestableDelegateTester1.class;
376         throwables[1] = Exception.class;
377         n = new NestableDelegateTester1(new Exception(msgs[1]));
378         d = new NestableDelegate(n);
379         doNestableDelegateGetThrowables(d, throwables, msgs);
380  
381         msgs = new String[5];
382         msgs[0] = "level 1";
383         msgs[1] = "level 2";
384         msgs[2] = null;
385         msgs[3] = "level 4";
386         msgs[4] = "level 5";
387         throwables = new Class[5];
388         throwables[0] = NestableDelegateTester1.class;
389         throwables[1] = NestableDelegateTester2.class;
390         throwables[2] = NestableDelegateTester1.class;
391         throwables[3] = NestableDelegateTester2.class;
392         throwables[4] = Exception.class;        
393         n = new NestableDelegateTester1(msgs[0], 
394                 new NestableDelegateTester2(msgs[1], 
395                     new NestableDelegateTester1(
396                         new NestableDelegateTester2(msgs[3], 
397                             new Exception(msgs[4])
398                         )
399                     )
400                 )
401             );
402         d = new NestableDelegate(n);
403         doNestableDelegateGetThrowables(d, throwables, msgs);
404     }
405     
406     private void doNestableDelegateGetThrowables(NestableDelegate d, Class[] classes, String[] msgs)
407     {
408         Throwable[] throwables = null;
409         String msg = null;
410 
411         throwables = d.getThrowables();
412         assertEquals("throwables length", classes.length, throwables.length);
413         for(int i = 0; i < classes.length; i++)
414         {
415             assertEquals("throwable class", classes[i], throwables[i].getClass());
416             Throwable t = throwables[i];
417             if(Nestable.class.isInstance(t))
418             {
419                 msg = ((Nestable) t).getMessage(0);
420             }
421             else
422             {
423                 msg = t.getMessage();
424             }
425             assertEquals("throwable message", msgs[i], msg);
426         }
427     }
428 
429     public void testIndexOfThrowable()
430     {
431         Nestable n = null;
432         NestableDelegate d = null;
433         String msgs[] = null;
434         Class[] throwables = null;
435         
436         msgs = new String[5];
437         msgs[0] = "level 1";
438         msgs[1] = "level 2";
439         msgs[2] = null;
440         msgs[3] = "level 4";
441         msgs[4] = "level 5";
442         throwables = new Class[5];
443         throwables[0] = NestableDelegateTester1.class;
444         throwables[1] = NestableDelegateTester2.class;
445         throwables[2] = NestableDelegateTester1.class;
446         throwables[3] = NestableDelegateTester2.class;
447         throwables[4] = EOFException.class;
448         int[] indexes = {0, 1, 0, 1, 4};
449         n = new NestableDelegateTester1(msgs[0], 
450                 new NestableDelegateTester2(msgs[1], 
451                     new NestableDelegateTester1(
452                         new NestableDelegateTester2(msgs[3], 
453                             new EOFException(msgs[4])
454                         )
455                     )
456                 )
457             );
458         d = new NestableDelegate(n);
459         for(int i = 0; i < throwables.length; i++)
460         {
461             doNestableDelegateIndexOfThrowable(d, throwables[i], 0, indexes[i], msgs[indexes[i]]);
462         }
463         doNestableDelegateIndexOfThrowable(d, NestableDelegateTester2.class, 2, 3, msgs[3]);
464         doNestableDelegateIndexOfThrowable(d, NestableDelegateTester1.class, 1, 2, msgs[2]);
465         doNestableDelegateIndexOfThrowable(d, NestableDelegateTester1.class, 3, -1, null);
466         doNestableDelegateIndexOfThrowable(d, NestableDelegateTester1.class, 4, -1, null);
467         doNestableDelegateIndexOfThrowable(d, EOFException.class, 2, 4, msgs[4]);
468         doNestableDelegateIndexOfThrowable(d, IOException.class, 2, 4, msgs[4]);
469         doNestableDelegateIndexOfThrowable(d, Exception.class, 2, 2, msgs[2]);
470         doNestableDelegateIndexOfThrowable(d, Exception.class, 0, 0, msgs[0]);
471         doNestableDelegateIndexOfThrowable(d, java.util.Date.class, 0, -1, null);
472         doNestableDelegateIndexOfThrowable(d, null, 0, -1, null);
473         
474         // Test for index out of bounds
475         try
476         {
477             int index = d.indexOfThrowable(NestableDelegateTester1.class, -1);
478             fail("method should have thrown IndexOutOfBoundsException");
479         }
480         catch(IndexOutOfBoundsException iooob)
481         {
482         }
483         try
484         {
485             int index = d.indexOfThrowable(NestableDelegateTester1.class, 5);
486             fail("method should have thrown IndexOutOfBoundsException");
487         }
488         catch(IndexOutOfBoundsException iooob)
489         {
490         }
491     }
492 
493     private void doNestableDelegateIndexOfThrowable(NestableDelegate d, Class type, int fromIndex, int expectedIndex, String expectedMsg)
494     {
495         Throwable t = null;
496         
497         int index = d.indexOfThrowable(type, fromIndex);
498         assertEquals("index of throwable " + (type == null ? "null" : type.getName()), expectedIndex, index);
499         if(expectedIndex > -1)
500         {
501             t = d.getThrowable(index);
502             if(expectedMsg != null)
503             {
504                 String msg = null;
505                 if(Nestable.class.isInstance(t))
506                 {
507                     msg = ((Nestable) t).getMessage(0);
508                 }
509                 else
510                 {
511                     msg = t.getMessage();
512                 }
513                 assertEquals("message of indexed throwable", expectedMsg, msg);
514             }
515         }
516     }
517     
518     public void testNestableDelegetePrintStackTrace()
519     {
520         int lineSepLen = lineSeparator.length();
521         int partialStackTraceLen = PARTIAL_STACK_TRACE.length();
522         Nestable ne3 = new ThrowableNestedNestable(new Exception("nested exception 3"));
523         NestableDelegate nd3 = new NestableDelegate(ne3);
524 
525         ByteArrayOutputStream baos1 = new ByteArrayOutputStream();
526         PrintStream ps1 = new PrintStream(baos1);
527         nd3.printStackTrace(ps1);
528         String stack1 = baos1.toString();
529         assertTrue("stack trace startsWith", stack1.startsWith(PARTIAL_STACK_TRACE));
530 
531         Nestable n = new NestableDelegateTester1("level 1", 
532                 new NestableDelegateTester2("level 2", 
533                     new NestableDelegateTester1(
534                         new NestableDelegateTester2("level 4", 
535                             new Exception("level 5")
536                         )
537                     )
538                 )
539             );
540         NestableDelegate d = new NestableDelegate(n);
541         
542         // Only testing the flags for jdk1.3 and below
543         if (!ExceptionUtils.isThrowableNested()) {
544             NestableDelegate.topDown = true; NestableDelegate.trimStackFrames = true;
545             checkStackTrace(d, true, true, NestableDelegateTester1.class.getName()+": level 1", 24);
546             NestableDelegate.topDown = true; NestableDelegate.trimStackFrames = false;
547             checkStackTrace(d, true, false, NestableDelegateTester1.class.getName()+": level 1", 80);
548             NestableDelegate.topDown = false; NestableDelegate.trimStackFrames = true;
549             checkStackTrace(d, false, true, "java.lang.Exception: level 5", 24);
550             NestableDelegate.topDown = false; NestableDelegate.trimStackFrames = false;
551             checkStackTrace(d, false, false, "java.lang.Exception: level 5", 80);
552             NestableDelegate.topDown = true; NestableDelegate.trimStackFrames = true;
553         }
554     }
555     private void checkStackTrace(NestableDelegate d, boolean topDown, boolean trimStackFrames,
556             String startsWith, int expCount) {
557         ByteArrayOutputStream baos1 = new ByteArrayOutputStream();
558         PrintStream ps1 = new PrintStream(baos1);
559         d.printStackTrace(ps1);
560         String stack1 = baos1.toString();
561         int actCount = countLines(stack1);
562         assertTrue("topDown: "+topDown+", trimStackFrames: "+trimStackFrames+" startsWith",
563             stack1.startsWith(startsWith));
564         // test is unreliable, as count varies depending on JUnit version/where main method is
565 //        assertEquals("topDown: "+topDown+", trimStackFrames: "+trimStackFrames+" lineCount",
566 //            expCount, actCount);
567     }
568     private int countLines(String s) {
569         if (s == null) return 0;
570         
571         int i = 0, ndx = -1;
572         while ((ndx = s.indexOf("\n", ndx+1)) != -1) {
573             i++;
574         }
575         return i;
576     }
577     
578     public static void main(String args[])
579     {
580         TestRunner.run(suite());
581     }
582 }
583 
584 /**
585  * Nestable and Throwable class which can be passed to the NestableDelegate
586  * constructor. Used for testing various methods which iterate through the
587  * nested causes.
588  */
589 class NestableDelegateTester1 extends Exception implements Nestable
590 {
591     private Throwable cause = null;
592 
593     public NestableDelegateTester1()
594     {
595         super();
596     }
597 
598     public NestableDelegateTester1(String reason, Throwable cause)
599     {
600         super(reason);
601         this.cause = cause;
602     }
603     
604     public NestableDelegateTester1(String reason)
605     {
606         super(reason);
607     }
608     
609     public NestableDelegateTester1(Throwable cause)
610     {
611         super();
612         this.cause = cause;
613     }
614     
615     /**
616      * @see Nestable#getThrowables()
617      * Returns zero-length <code>Throwable</code> array for this test.
618      */
619     public Throwable[] getThrowables()
620     {
621         return new Throwable[0];
622     }
623     
624     /**
625      * @see Nestable#getMessages()
626      * Returns zero-length String array for this test.
627      */
628     public String[] getMessages()
629     {
630         return new String[0];
631     }
632     
633     /**
634      * @see Nestable#indexOfThrowable(Class)
635      * Returns -1 for this test.
636      */
637     public int indexOfThrowable(Class type)
638     {
639         return -1;
640     }
641     
642     /**
643      * @see Nestable#getThrowable(int)
644      * Returns <code>null</code> for this test.
645      */
646     public Throwable getThrowable(int index)
647     {
648         return null;
649     }
650     
651     /**
652      * @see Nestable#getThrowableCount()
653      * Returns 1 for this test.
654      */
655     public int getThrowableCount()
656     {
657         return 1;
658     }
659     
660     /**
661      * @see Nestable#getCause()
662      */
663     public Throwable getCause()
664     {
665         return cause;
666     }
667     
668     /**
669      * Empty method to satisfy the implemented interface. Does nothing
670      * in this test.
671      *
672      * @param out The writer to use.
673      */
674     public void printPartialStackTrace(PrintWriter out)
675     {
676         super.printStackTrace(out);
677     }
678     
679     /**
680      * @see Nestable#getMessage(int)
681      */
682     public String getMessage(int index)
683     {
684         if(index == 0)
685         {
686             return super.getMessage();
687         }
688         else
689         {
690             return "";
691         }
692     }
693     
694     /**
695      * @see Nestable#indexOfThrowable(Class, int)
696      * Returns -1 for this test.
697      */
698     public int indexOfThrowable(Class type, int fromIndex)
699     {
700         return -1;
701     }
702     
703 }
704 
705 /**
706  * Nestable and Throwable class which can be passed to the NestableDelegate
707  * constructor. Used for testing various methods which iterate through the
708  * nested causes.
709  */
710 class NestableDelegateTester2 extends Throwable implements Nestable
711 {
712     private Throwable cause = null;
713 
714     public NestableDelegateTester2()
715     {
716         super();
717     }
718     
719     public NestableDelegateTester2(String reason, Throwable cause)
720     {
721         super(reason);
722         this.cause = cause;
723     }
724     
725     public NestableDelegateTester2(String reason)
726     {
727         super(reason);
728     }
729     
730     public NestableDelegateTester2(Throwable cause)
731     {
732         super();
733         this.cause = cause;
734     }
735     
736     /**
737      * @see Nestable#getThrowables()
738      * Returns zero-length <code>Throwable</code> array for this test.
739      */
740     public Throwable[] getThrowables()
741     {
742         return new Throwable[0];
743     }
744     
745     /**
746      * @see Nestable#getMessages()
747      * Returns zero-length String array for this test.
748      */
749     public String[] getMessages()
750     {
751         return new String[0];
752     }
753     
754     /**
755      * @see Nestable#indexOfThrowable(Class)
756      * Returns -1 for this test.
757      */
758     public int indexOfThrowable(Class type)
759     {
760         return -1;
761     }
762     
763     /**
764      * @see Nestable#getThrowable(int)
765      * Returns <code>null</code> for this test.
766      */
767     public Throwable getThrowable(int index)
768     {
769         return null;
770     }
771     
772     /**
773      * @see Nestable#getThrowableCount()
774      * Returns 1 for this test.
775      *
776      * @return 1
777      */
778     public int getThrowableCount()
779     {
780         return 1;
781     }
782     
783     /**
784      * @see Nestable#getCause()
785      */
786     public Throwable getCause()
787     {
788         return cause;
789     }
790     
791     /**
792      * Empty method to satisfy the implemented interface. Does nothing
793      * in this test.
794      *
795      * @param out The writer to use.
796      */
797     public void printPartialStackTrace(PrintWriter out)
798     {
799         super.printStackTrace(out);
800     }
801     
802     /**
803      * @see Nestable#getMessage(int)
804      */
805     public String getMessage(int index)
806     {
807         if(index == 0)
808         {
809             return super.getMessage();
810         }
811         else
812         {
813             return "";
814         }
815     }
816     
817     /**
818      * @see Nestable#indexOfThrowable(Class, int)     
819      * Returns -1 for this test.
820      */
821     public int indexOfThrowable(Class type, int fromIndex)
822     {
823         return -1;
824     }
825     
826 }
827 
828 /**
829  * Used to test that the constructor passes when passed a throwable cause
830  * And, the NestableDelegate.getMessage() returns the message from underlying 
831  * nestable (which also has to be a Throwable).
832  */
833 class ThrowableNestable extends Throwable implements Nestable
834 {
835     private Throwable cause = new Exception("ThrowableNestable cause");
836 
837     /**
838      * @see Nestable#getThrowableCount()
839      * Returns 1 for this test.
840      */
841     public int getThrowableCount()
842     {
843         return 1;
844     }
845     
846     /**
847      * @see Nestable#getMessage()
848      * Returns the hard-coded string "ThrowableNestable exception" for this
849      * test.
850      */
851     public String getMessage()
852     {
853         return "ThrowableNestable exception";
854     }
855 
856     /**
857      * @see Nestable#getMessage(int)
858      * Returns the hard-coded string "ThrowableNestable exception" for this
859      * test.
860      */
861     public String getMessage(int index)
862     {
863         return getMessage();
864     }
865 
866     /**
867      * @see Nestable#getMessages()
868      * Returns single-element string array with "ThrowableNestable exception".
869      */
870     public String[] getMessages()
871     {
872         String msgs[] = new String[1];
873         msgs[0] = getMessage();
874         return msgs;
875     }
876     
877     /**
878      * @see Nestable#getCause()
879      */
880     public Throwable getCause()
881     {
882         return cause;
883     }
884 
885     /**
886      * @see Nestable#printStackTrace(PrintWriter)
887      * Empty method to satisfy the implemented interface. Does nothing
888      * in this test.
889      */
890     public void printStackTrace(PrintWriter out)
891     {
892     }
893     
894     /**
895      * @see Nestable#printPartialStackTrace(PrintWriter)
896      * Empty method to satisfy the implemented interface. Does nothing
897      * in this test.
898      */
899     public void printPartialStackTrace(PrintWriter out)
900     {
901     }
902     
903     /**
904      * @see Nestable#getThrowable(int)
905      */
906     public Throwable getThrowable(int index)
907     {
908         return cause;
909     }
910     
911     /**
912      * @see Nestable#getThrowables()
913      */
914     public Throwable[] getThrowables()
915     {
916         Throwable throwables[] = new Throwable[1];
917         throwables[0] = cause;
918         return throwables;
919     }
920     
921     /**
922      * @see Nestable#indexOfThrowable(Class)
923      */
924     public int indexOfThrowable(Class type)
925     {
926         if(Exception.class.isInstance(type))
927         {
928             return 0;
929         }
930         return -1;
931     }
932     
933     /**
934      * @see Nestable#indexOfThrowable(Class,int)
935      */
936     public int indexOfThrowable(Class type, int fromIndex)
937     {
938         return indexOfThrowable(type);
939     }
940     
941 }
942 
943 /**
944  * Nestable and Throwable class which takes in a 'cause' object.
945  * Returns a message wrapping the 'cause' message
946  * Prints a fixed stack trace and partial stack trace.
947  */
948 class ThrowableNestedNestable extends Throwable implements Nestable
949 {
950     private Throwable cause = null;
951     
952     public ThrowableNestedNestable(Throwable cause)
953     {
954         this.cause = cause;
955     }
956     
957     /**
958      * @see Nestable#getThrowableCount()
959      * Returns 1 for this test.
960      */
961     public int getThrowableCount()
962     {
963         return 1;
964     }
965     
966     /**
967      * @see Nestable#getMessage()
968      * For this test, returns "ThrowableNestable exception (" appended to the
969      * message of the cause specified in the constructor.
970      */
971     public String getMessage()
972     {
973         return "ThrowableNestedNestable exception (" + cause.getMessage() + ")";
974     }
975 
976     /**
977      * @see Nestable#getMessage(int)
978      * For this test, returns "ThrowableNestable exception (" appended to the
979      * message of the cause specified in the constructor.
980      */
981     public String getMessage(int index)
982     {
983         return "ThrowableNestedNestable exception (" + cause.getMessage() + ")";
984     }
985     
986     /**
987      * @see Nestable#getMessages()
988      * For this test, returns a single-element string array containing
989      * "ThrowableNestable exception (" appended to the
990      * message of the cause specified in the constructor.
991      */
992     public String[] getMessages()
993     {
994         String[] msgs = new String[1];
995         msgs[0] = "ThrowableNestedNestable exception (" + cause.getMessage() + ")";
996         return msgs;
997     }
998     
999     /**
1000      * @see Nestable#getCause()
1001      */
1002     public Throwable getCause()
1003     {
1004         return cause;
1005     }
1006     
1007     /**
1008      * @see Nestable#printStackTrace(PrintWriter)
1009      * For this test, writes the string
1010      * "ThrowableNestedNestable stack trace place-holder" to the print writer.
1011      */
1012     public void printStackTrace(PrintWriter out)
1013     {
1014         out.println("ThrowableNestedNestable stack trace place-holder");
1015     }
1016     
1017     /**
1018      * @see Nestable#printPartialStackTrace(PrintWriter)
1019      * For this test, writes the string
1020      * "ThrowableNestedNestable partial stack trace place-holder" to the print
1021      * writer.
1022      */
1023     public void printPartialStackTrace(PrintWriter out)
1024     {
1025         out.println("ThrowableNestedNestable partial stack trace place-holder");
1026     }
1027     
1028     /**
1029      * @see Nestable#getThrowable(int)
1030      */
1031     public Throwable getThrowable(int index)
1032     {
1033         return cause;
1034     }
1035     
1036     /**
1037      * @see Nestable#getThrowables()
1038      */
1039     public Throwable[] getThrowables()
1040     {
1041         Throwable throwables[] = new Throwable[1];
1042         throwables[0] = cause;
1043         return throwables;
1044     }
1045     
1046     /**
1047      * @see Nestable#indexOfThrowable(Class)
1048      */
1049     public int indexOfThrowable(Class type)
1050     {
1051         if(Exception.class.isInstance(type))
1052         {
1053             return 0;
1054         }
1055         return -1;
1056     }
1057     
1058     /**
1059      * @see Nestable#indexOfThrowable(Class, int)
1060      */
1061     public int indexOfThrowable(Class type, int fromIndex)
1062     {
1063         return indexOfThrowable(type);
1064     }
1065     
1066 }
1067 
1068 /**
1069  * Used to test that the constructor fails when passed a non-throwable cause
1070  */
1071 class NonThrowableNestable implements Nestable
1072 {
1073     /**
1074      * @see Nestable#getThrowableCount()
1075      * Returns 1 for this test.
1076      */
1077     public int getThrowableCount()
1078     {
1079         return 1;
1080     }
1081     
1082     /**
1083      * @see Nestable#getMessage()
1084      * Returns the string "non-throwable" for this test.
1085      */
1086     public String getMessage()
1087     {
1088         return "non-throwable";
1089     }
1090 
1091     /**
1092      * @see Nestable#getMessage(int)
1093      * Returns the string "non-throwable" for this test.
1094      */
1095     public String getMessage(int index)
1096     {
1097         return "non-throwable";
1098     }
1099     
1100     /**
1101      * @see Nestable#getMessage()
1102      * Returns a single-element array containing the string "non-throwable" for
1103      * this test.
1104      */
1105     public String[] getMessages()
1106     {
1107         String[] msgs = new String[1];
1108         msgs[0] = "non-throwable";
1109         return msgs;
1110     }
1111     
1112     /**
1113      * @see Nestable#getCause()
1114      * Returns <code>null</code> for this test.
1115      */
1116     public Throwable getCause()
1117     {
1118         return null;
1119     }
1120     
1121     /**
1122      * @see Nestable#printStackTrace(PrintWriter)
1123      * Empty method to satisfy the implemented interface. Does nothing
1124      * in this test.
1125      */
1126     public void printStackTrace(PrintWriter out)
1127     {
1128     }
1129     
1130     /**
1131      * @see Nestable#printStackTrace(PrintStream)
1132      * Empty method to satisfy the implemented interface. Does nothing
1133      * in this test.
1134      */
1135     public void printStackTrace(PrintStream out)
1136     {
1137     }
1138     
1139     /**
1140      * @see Nestable#printPartialStackTrace(PrintWriter)
1141      * Empty method to satisfy the implemented interface. Does nothing
1142      * in this test.
1143      */
1144     public void printPartialStackTrace(PrintWriter out)
1145     {
1146     }
1147     
1148 
1149     /**
1150      * @see Nestable#getThrowable(int)
1151      * Returns <code>null</code> for this test.
1152      */
1153     public Throwable getThrowable(int index)
1154     {
1155         return null;
1156     }
1157     
1158     /**
1159      * @see Nestable#getThrowables()
1160      * Returns zero-length <code>Throwable</code> array.
1161      */
1162     public Throwable[] getThrowables()
1163     {
1164         return new Throwable[0];
1165     }
1166     
1167     /**
1168      * @see Nestable#indexOfThrowable(Class)
1169      * Returns -1 for this test.
1170      */
1171     public int indexOfThrowable(Class type)
1172     {
1173         return -1;
1174     }
1175     
1176     /**
1177      * @see Nestable#indexOfThrowable(Class, int)
1178      * Returns -1 for this test.
1179      */
1180     public int indexOfThrowable(Class type, int fromIndex)
1181     {
1182         return -1;
1183     }
1184     
1185 }