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 public class TestListenerInvocationHandler
33 implements InvocationHandler
34 {
35
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<FailedTest> failedTestsSet = new HashSet<FailedTest>();
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
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
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 }