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