View Javadoc

1   /*
2    *  soapUI, copyright (C) 2006 eviware.com 
3    *
4    *  soapUI is free software; you can redistribute it and/or modify it under the 
5    *  terms of the GNU Lesser General Public License as published by the Free Software Foundation; 
6    *  either version 2.1 of the License, or (at your option) any later version.
7    *
8    *  soapUI is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without 
9    *  even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
10   *  See the GNU Lesser General Public License for more details at gnu.org.
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 			// create state for testcase if specified
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 				// discard?
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 }