1
2
3
4
5
6
7
8
9
10
11
12
13 package com.eviware.soapui.impl.wsdl.testcase;
14
15 import java.util.ArrayList;
16 import java.util.Collections;
17 import java.util.List;
18 import java.util.concurrent.ExecutorService;
19 import java.util.concurrent.Executors;
20 import java.util.concurrent.Future;
21
22 import org.apache.commons.httpclient.HttpState;
23
24 import com.eviware.soapui.impl.wsdl.teststeps.WsdlTestStep;
25 import com.eviware.soapui.model.support.PropertiesMap;
26 import com.eviware.soapui.model.testsuite.TestCase;
27 import com.eviware.soapui.model.testsuite.TestRunContext;
28 import com.eviware.soapui.model.testsuite.TestRunListener;
29 import com.eviware.soapui.model.testsuite.TestRunner;
30 import com.eviware.soapui.model.testsuite.TestStep;
31 import com.eviware.soapui.model.testsuite.TestStepResult;
32 import com.eviware.soapui.model.testsuite.TestStepResult.TestStepStatus;
33 import com.eviware.soapui.support.UISupport;
34
35 /***
36 * WSDL TestCase Runner - runs all steps in a testcase and collects performance data
37 *
38 * @author Ole.Matzura
39 */
40
41 public class WsdlTestCaseRunner implements Runnable, TestRunner
42 {
43 private TestRunListener [] listeners;
44 private final WsdlTestCase testCase;
45 private Status status;
46 private Throwable error;
47 private WsdlTestRunContext runContext;
48 private List<TestStepResult> testStepResults = new ArrayList<TestStepResult>();
49 private int gotoStepIndex;
50 private long startTime;
51 private String reason;
52 private volatile Future<?> future;
53 private int id;
54 private final static ExecutorService threadPool = Executors.newCachedThreadPool();
55
56 private static int idCounter = 0;
57
58 public WsdlTestCaseRunner( WsdlTestCase testCase, PropertiesMap properties )
59 {
60 this.testCase = testCase;
61 status = Status.INITIALIZED;
62 runContext = new WsdlTestRunContext( this, properties );
63 id = ++idCounter;
64 }
65
66 public WsdlTestRunContext getRunContext()
67 {
68 return runContext;
69 }
70
71 public void start( boolean async )
72 {
73 status = Status.RUNNING;
74 if( async )
75 future = threadPool.submit(this);
76 else
77 run();
78 }
79
80 public void cancel( String reason )
81 {
82 if( status == Status.CANCELED || status == Status.FINISHED || status == Status.FAILED ||
83 runContext == null ) return;
84 TestStep currentStep = runContext.getCurrentStep();
85 if( currentStep != null )
86 currentStep.cancel();
87 status = Status.CANCELED;
88 this.reason = reason;
89 }
90
91 public void fail( String reason )
92 {
93 if( status == Status.CANCELED || status == Status.FAILED ||
94 runContext == null ) return;
95 TestStep currentStep = runContext.getCurrentStep();
96 if( currentStep != null )
97 currentStep.cancel();
98 status = Status.FAILED;
99 this.reason = reason;
100 }
101
102 public Status getStatus()
103 {
104 return status;
105 }
106
107
108 public int getId()
109 {
110 return id;
111 }
112
113 public void run()
114 {
115 WsdlTestStep[] testSteps = testCase.getTestSteps();
116
117 try
118 {
119 status = Status.RUNNING;
120 startTime = System.currentTimeMillis();
121
122 gotoStepIndex = -1;
123 testStepResults.clear();
124
125 listeners = testCase.getTestRunListeners();
126
127
128 if( testCase.getKeepSession() )
129 {
130 runContext.setProperty( TestRunContext.HTTP_STATE_PROPERTY, new HttpState() );
131 }
132
133 for( WsdlTestStep testStep : testSteps )
134 {
135 testStep.prepare( this, runContext );
136 if( status == Status.CANCELED || status == Status.FAILED )
137 return;
138 }
139
140 for (int i = 0; i < listeners.length; i++)
141 {
142 listeners[i].beforeRun( this, runContext );
143 if( status == Status.CANCELED || status == Status.FAILED )
144 return;
145 }
146
147 int currentStepIndex = runContext.getCurrentStepIndex();
148
149 for ( currentStepIndex = 0; status != Status.CANCELED && currentStepIndex < testSteps.length; currentStepIndex++)
150 {
151 TestStep currentStep = runContext.getCurrentStep();
152 for (int i = 0; i < listeners.length; i++) {
153 listeners[i].beforeStep(this, runContext );
154 if( status == Status.CANCELED || status == Status.FAILED )
155 return;
156 }
157
158 TestStepResult stepResult = currentStep.run( this, runContext );
159 testStepResults.add( stepResult );
160
161 for (int i = 0; i < listeners.length; i++)
162 {
163 listeners[i].afterStep( this, runContext, stepResult );
164 }
165
166
167 if( stepResult.getStatus() == TestStepStatus.OK && testCase.getDiscardOkResults() &&
168 !stepResult.isDiscarded() )
169 {
170 stepResult.discard();
171 }
172
173 if( stepResult.getStatus() == TestStepStatus.FAILED )
174 {
175 if( testCase.getFailOnError() )
176 {
177 fail( "Cancelling due to failed test step" );
178 }
179 else
180 {
181 runContext.setProperty( TestRunner.Status.class.getName(), TestRunner.Status.FAILED );
182 }
183 }
184
185 if( status == Status.CANCELED || status == Status.FAILED )
186 return;
187
188 if( gotoStepIndex != -1 )
189 {
190 currentStepIndex = gotoStepIndex-1;
191 gotoStepIndex = -1;
192 }
193
194 runContext.setCurrentStep( currentStepIndex+1 );
195 }
196
197 if( runContext.getProperty( TestRunner.Status.class.getName() ) == TestRunner.Status.FAILED &&
198 testCase.getFailTestCaseOnErrors() )
199 {
200 fail( "Failing due to failed test step" );
201 }
202 }
203 catch (Throwable t)
204 {
205 t.printStackTrace();
206
207 if( t instanceof OutOfMemoryError &&
208 UISupport.confirm( "Exit now without saving?", "Out of Memory Error" ) )
209 {
210 System.exit( 0 );
211 }
212
213 status = Status.FAILED;
214 error = t;
215 }
216 finally
217 {
218 if( status == Status.RUNNING )
219 {
220 status = Status.FINISHED;
221 }
222
223 for( WsdlTestStep testStep : testSteps )
224 {
225 testStep.finish( this, runContext );
226 }
227
228 notifyAfterRun();
229 }
230 }
231
232 private void notifyAfterRun()
233 {
234 if( listeners == null || listeners.length == 0 )
235 return;
236
237 for (int i = 0; i < listeners.length; i++)
238 {
239 listeners[i].afterRun( this, runContext );
240 }
241 }
242
243 public TestCase getTestCase() {
244 return testCase;
245 }
246
247 public synchronized Status waitUntilFinished()
248 {
249 if (future != null)
250 {
251 if (!future.isDone())
252 {
253 try
254 {
255 future.get();
256 }
257 catch (Exception e)
258 {
259 e.printStackTrace();
260 }
261 }
262 }
263 else
264 throw new RuntimeException("cannot wait on null future");
265
266
267 return getStatus();
268 }
269
270 public long getTimeTaken()
271 {
272 long sum = 0;
273 for( int c = 0; c < testStepResults.size(); c++ )
274 {
275 TestStepResult testStepResult = testStepResults.get( c );
276 if( testStepResult != null )
277 sum += testStepResult.getTimeTaken();
278 }
279
280 return sum;
281 }
282
283 public long getStartTime()
284 {
285 return startTime;
286 }
287
288 public Throwable getError()
289 {
290 return error;
291 }
292
293 public String getReason()
294 {
295 return reason == null ? error == null ? null : error.toString() : reason;
296 }
297
298 public List<TestStepResult> getResults()
299 {
300 return Collections.unmodifiableList( testStepResults );
301 }
302
303 public void gotoStep(int index)
304 {
305 gotoStepIndex = index;
306 }
307
308 public void gotoStepByName(String stepName)
309 {
310 TestStep testStep = getTestCase().getTestStepByName( stepName );
311 if( testStep != null )
312 gotoStep( getTestCase().getIndexOfTestStep( testStep));
313 }
314 }