View Javadoc

1   package org.apache.maven.surefire.junit;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *     http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import java.lang.reflect.InvocationHandler;
23  import java.lang.reflect.InvocationTargetException;
24  import java.lang.reflect.Method;
25  import java.util.HashSet;
26  import java.util.Set;
27  import org.apache.maven.surefire.report.LegacyPojoStackTraceWriter;
28  import org.apache.maven.surefire.report.ReportEntry;
29  import org.apache.maven.surefire.report.RunListener;
30  import org.apache.maven.surefire.report.SimpleReportEntry;
31  
32  public class TestListenerInvocationHandler
33      implements InvocationHandler
34  {
35      // The String names of the four methods in interface junit.framework.TestListener
36      private static final String START_TEST = "startTest";
37  
38      private static final String ADD_FAILURE = "addFailure";
39  
40      private static final String ADD_ERROR = "addError";
41  
42      private static final String END_TEST = "endTest";
43  
44      private final Set failedTestsSet = new HashSet();
45  
46      private RunListener reporter;
47  
48      private static final Class[] EMPTY_CLASS_ARRAY = new Class[]{ };
49  
50      private static final String[] EMPTY_STRING_ARRAY = new String[]{ };
51  
52      private static class FailedTest
53      {
54          private Object testThatFailed;
55  
56          private Thread threadOnWhichTestFailed;
57  
58          FailedTest( Object testThatFailed, Thread threadOnWhichTestFailed )
59          {
60              if ( testThatFailed == null )
61              {
62                  throw new NullPointerException( "testThatFailed is null" );
63              }
64  
65              if ( threadOnWhichTestFailed == null )
66              {
67                  throw new NullPointerException( "threadOnWhichTestFailed is null" );
68              }
69  
70              this.testThatFailed = testThatFailed;
71  
72              this.threadOnWhichTestFailed = threadOnWhichTestFailed;
73          }
74  
75          public boolean equals( Object obj )
76          {
77              boolean retVal = true;
78  
79              if ( obj == null || getClass() != obj.getClass() )
80              {
81                  retVal = false;
82              }
83              else
84              {
85                  FailedTest ft = (FailedTest) obj;
86  
87                  if ( ft.testThatFailed != testThatFailed )
88                  {
89                      retVal = false;
90                  }
91                  else if ( !ft.threadOnWhichTestFailed.equals( threadOnWhichTestFailed ) )
92                  {
93                      retVal = false;
94                  }
95              }
96  
97              return retVal;
98          }
99  
100         public int hashCode()
101         {
102             return threadOnWhichTestFailed.hashCode();
103         }
104     }
105 
106     public TestListenerInvocationHandler( RunListener reporter )
107     {
108         if ( reporter == null )
109         {
110             throw new NullPointerException( "reporter is null" );
111         }
112 
113         this.reporter = reporter;
114     }
115 
116     public Object invoke( Object proxy, Method method, Object[] args )
117         throws Throwable
118     {
119         String methodName = method.getName();
120 
121         if ( methodName.equals( START_TEST ) )
122         {
123             handleStartTest( args );
124         }
125         else if ( methodName.equals( ADD_ERROR ) )
126         {
127             handleAddError( args );
128         }
129         else if ( methodName.equals( ADD_FAILURE ) )
130         {
131             handleAddFailure( args );
132         }
133         else if ( methodName.equals( END_TEST ) )
134         {
135             handleEndTest( args );
136         }
137 
138         return null;
139     }
140 
141     // Handler for TestListener.startTest(Test)
142     public void handleStartTest( Object[] args )
143     {
144         ReportEntry report = new SimpleReportEntry( args[0].getClass().getName(), args[0].toString() );
145 
146         reporter.testStarting( report );
147     }
148 
149     // Handler for TestListener.addFailure(Test, Throwable)
150     private void handleAddError( Object[] args )
151         throws IllegalAccessException, InvocationTargetException
152     {
153         ReportEntry report = SimpleReportEntry.withException( args[0].getClass().getName(), args[0].toString(),
154                                                               getStackTraceWriter( args ) );
155 
156         reporter.testError( report );
157 
158         failedTestsSet.add( new FailedTest( args[0], Thread.currentThread() ) );
159     }
160 
161     private LegacyPojoStackTraceWriter getStackTraceWriter( Object[] args )
162         throws IllegalAccessException, InvocationTargetException
163     {
164         String testName;
165 
166         try
167         {
168             Method m = args[0].getClass().getMethod( "getName", EMPTY_CLASS_ARRAY );
169             testName = (String) m.invoke( args[0], EMPTY_STRING_ARRAY );
170         }
171         catch ( NoSuchMethodException e )
172         {
173             testName = "UNKNOWN";
174         }
175 
176         return new LegacyPojoStackTraceWriter( args[0].getClass().getName(), testName, (Throwable) args[1] );
177     }
178 
179     private void handleAddFailure( Object[] args )
180         throws IllegalAccessException, InvocationTargetException
181     {
182         ReportEntry report = SimpleReportEntry.withException( args[0].getClass().getName(), args[0].toString(),
183                                                               getStackTraceWriter( args ) );
184 
185         reporter.testFailed( report );
186 
187         failedTestsSet.add( new FailedTest( args[0], Thread.currentThread() ) );
188     }
189 
190     private void handleEndTest( Object[] args )
191     {
192         boolean testHadFailed = failedTestsSet.remove( new FailedTest( args[0], Thread.currentThread() ) );
193 
194         if ( !testHadFailed )
195         {
196             ReportEntry report = new SimpleReportEntry( args[0].getClass().getName(), args[0].toString() );
197 
198             reporter.testSucceeded( report );
199         }
200     }
201 }