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 org.apache.maven.surefire.report.ReportEntry;
23  import org.apache.maven.surefire.report.ReporterManager;
24  
25  import java.lang.reflect.InvocationHandler;
26  import java.lang.reflect.InvocationTargetException;
27  import java.lang.reflect.Method;
28  import java.util.HashSet;
29  import java.util.Set;
30  
31  public class TestListenerInvocationHandler
32      implements InvocationHandler
33  {
34      // The String names of the four methods in interface junit.framework.TestListener
35      private static final String START_TEST = "startTest";
36  
37      private static final String ADD_FAILURE = "addFailure";
38  
39      private static final String ADD_ERROR = "addError";
40  
41      private static final String END_TEST = "endTest";
42  
43      private Set failedTestsSet = new HashSet();
44  
45      private ReporterManager reportManager;
46  
47      private static final Class[] EMPTY_CLASS_ARRAY = new Class[]{};
48  
49      private static final String[] EMPTY_STRING_ARRAY = new String[]{};
50  
51      private static class FailedTest
52      {
53          private Object testThatFailed;
54  
55          private Thread threadOnWhichTestFailed;
56  
57          FailedTest( Object testThatFailed, Thread threadOnWhichTestFailed )
58          {
59              if ( testThatFailed == null )
60              {
61                  throw new NullPointerException( "testThatFailed is null" );
62              }
63  
64              if ( threadOnWhichTestFailed == null )
65              {
66                  throw new NullPointerException( "threadOnWhichTestFailed is null" );
67              }
68  
69              this.testThatFailed = testThatFailed;
70  
71              this.threadOnWhichTestFailed = threadOnWhichTestFailed;
72          }
73  
74          public boolean equals( Object obj )
75          {
76              boolean retVal = true;
77  
78              if ( obj == null || getClass() != obj.getClass() )
79              {
80                  retVal = false;
81              }
82              else
83              {
84                  FailedTest ft = (FailedTest) obj;
85  
86                  if ( ft.testThatFailed != testThatFailed )
87                  {
88                      retVal = false;
89                  }
90                  else if ( !ft.threadOnWhichTestFailed.equals( threadOnWhichTestFailed ) )
91                  {
92                      retVal = false;
93                  }
94              }
95  
96              return retVal;
97          }
98  
99          public int hashCode()
100         {
101             return threadOnWhichTestFailed.hashCode();
102         }
103     }
104 
105     public TestListenerInvocationHandler( ReporterManager reportManager, Object instanceOfTestResult,
106                                           ClassLoader loader )
107     {
108         if ( reportManager == null )
109         {
110             throw new NullPointerException( "reportManager is null" );
111         }
112 
113         if ( instanceOfTestResult == null )
114         {
115             throw new NullPointerException( "instanceOfTestResult is null" );
116         }
117 
118         if ( loader == null )
119         {
120             throw new NullPointerException( "loader is null" );
121         }
122 
123         this.reportManager = reportManager;
124     }
125 
126     public Object invoke( Object proxy, Method method, Object[] args )
127         throws Throwable
128     {
129         String methodName = method.getName();
130 
131         if ( methodName.equals( START_TEST ) )
132         {
133             handleStartTest( args );
134         }
135         else if ( methodName.equals( ADD_ERROR ) )
136         {
137             handleAddError( args );
138         }
139         else if ( methodName.equals( ADD_FAILURE ) )
140         {
141             handleAddFailure( args );
142         }
143         else if ( methodName.equals( END_TEST ) )
144         {
145             handleEndTest( args );
146         }
147 
148         return null;
149     }
150 
151     // Handler for TestListener.startTest(Test)
152     public void handleStartTest( Object[] args )
153     {
154         ReportEntry report = new ReportEntry( args[0].getClass().getName(), args[0].toString(), args[0].getClass().getName() );
155 
156         reportManager.testStarting( report );
157     }
158 
159     // Handler for TestListener.addFailure(Test, Throwable)
160     private void handleAddError( Object[] args )
161         throws IllegalAccessException, InvocationTargetException
162     {
163         ReportEntry report =
164             new ReportEntry( args[0].getClass().getName(), args[0].toString(), args[1].toString(), getStackTraceWriter( args ) );
165 
166         reportManager.testError( report );
167 
168         failedTestsSet.add( new FailedTest( args[0], Thread.currentThread() ) );
169     }
170 
171     private JUnitStackTraceWriter getStackTraceWriter( Object[] args )
172         throws IllegalAccessException, InvocationTargetException
173     {
174         String testName;
175 
176         try
177         {
178             Method m = args[0].getClass().getMethod( "getName", EMPTY_CLASS_ARRAY );
179             testName = (String) m.invoke( args[0], EMPTY_STRING_ARRAY );
180         }
181         catch ( NoSuchMethodException e )
182         {
183             testName = "UNKNOWN";
184         }
185 
186         return new JUnitStackTraceWriter( args[0].getClass().getName(), testName, (Throwable) args[1] );
187     }
188 
189     private void handleAddFailure( Object[] args )
190         throws IllegalAccessException, InvocationTargetException
191     {
192         ReportEntry report =
193             new ReportEntry( args[0].getClass().getName(), args[0].toString(), args[1].toString(), getStackTraceWriter( args ) );
194 
195         reportManager.testFailed( report );
196 
197         failedTestsSet.add( new FailedTest( args[0], Thread.currentThread() ) );
198     }
199 
200     private void handleEndTest( Object[] args )
201     {
202         boolean testHadFailed = failedTestsSet.remove( new FailedTest( args[0], Thread.currentThread() ) );
203 
204         if ( !testHadFailed )
205         {
206             ReportEntry report = new ReportEntry( args[0].getClass().getName(), args[0].toString(), args[0].getClass().getName() );
207 
208             reportManager.testSucceeded( report );
209         }
210     }
211 }