View Javadoc

1   /*
2    *  soapUI, copyright (C) 2004-2010 eviware.com 
3    *
4    *  soapUI is free software; you can redistribute it and/or modify it under the 
5    *  terms of version 2.1 of the GNU Lesser General Public License as published by 
6    *  the Free Software Foundation.
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.Arrays;
16  import java.util.HashSet;
17  import java.util.List;
18  import java.util.Set;
19  
20  import com.eviware.soapui.SoapUI;
21  import com.eviware.soapui.impl.wsdl.WsdlProject;
22  import com.eviware.soapui.impl.wsdl.WsdlTestSuite;
23  import com.eviware.soapui.impl.wsdl.support.AbstractTestRunner;
24  import com.eviware.soapui.model.project.Project;
25  import com.eviware.soapui.model.propertyexpansion.DefaultPropertyExpansionContext;
26  import com.eviware.soapui.model.support.TestSuiteRunListenerAdapter;
27  import com.eviware.soapui.model.testsuite.ProjectRunListener;
28  import com.eviware.soapui.model.testsuite.ProjectRunner;
29  import com.eviware.soapui.model.testsuite.TestSuite;
30  import com.eviware.soapui.model.testsuite.TestSuiteRunContext;
31  import com.eviware.soapui.model.testsuite.TestSuiteRunListener;
32  import com.eviware.soapui.model.testsuite.TestSuiteRunner;
33  import com.eviware.soapui.model.testsuite.TestSuite.TestSuiteRunType;
34  import com.eviware.soapui.support.types.StringToObjectMap;
35  
36  public class WsdlProjectRunner extends AbstractTestRunner<WsdlProject, WsdlProjectRunContext> implements ProjectRunner
37  {
38  	private ProjectRunListener[] listeners;
39  	private Set<TestSuiteRunner> finishedRunners = new HashSet<TestSuiteRunner>();
40  	private Set<TestSuiteRunner> activeRunners = new HashSet<TestSuiteRunner>();
41  	private int currentTestSuiteIndex;
42  	private WsdlTestSuite currentTestSuite;
43  	private TestSuiteRunListener internalTestRunListener = new InternalTestSuiteRunListener();
44  
45  	public WsdlProjectRunner( WsdlProject project, StringToObjectMap properties )
46  	{
47  		super( project, properties );
48  	}
49  
50  	public WsdlProjectRunContext createContext( StringToObjectMap properties )
51  	{
52  		return new WsdlProjectRunContext( this, properties );
53  	}
54  
55  	public void onCancel( String reason )
56  	{
57  		for( TestSuiteRunner runner : activeRunners.toArray( new TestSuiteRunner[activeRunners.size()] ) )
58  		{
59  			runner.cancel( reason );
60  		}
61  	}
62  
63  	public void onFail( String reason )
64  	{
65  		for( TestSuiteRunner runner : activeRunners.toArray( new TestSuiteRunner[activeRunners.size()] ) )
66  		{
67  			runner.fail( reason );
68  		}
69  	}
70  
71  	public void internalRun( WsdlProjectRunContext runContext ) throws Exception
72  	{
73  		WsdlProject project = getTestRunnable();
74  
75  		listeners = project.getProjectRunListeners();
76  		project.runBeforeRunScript( runContext, this );
77  		if( !isRunning() )
78  		{
79  			return;
80  		}
81  
82  		if( project.getTimeout() > 0 )
83  		{
84  			startTimeoutTimer( project.getTimeout() );
85  		}
86  		
87  		notifyBeforeRun();
88  		if( !isRunning() )
89  			return;
90  
91  		if( project.getRunType() == TestSuiteRunType.SEQUENTIAL )
92  		{
93  			runSequential( project, runContext );
94  		}
95  		else if( project.getRunType() == TestSuiteRunType.PARALLEL )
96  		{
97  			runParallel( project, runContext );
98  		}
99  	}
100 
101 	private void runParallel( WsdlProject project, WsdlProjectRunContext runContext )
102 	{
103 		currentTestSuiteIndex = -1;
104 		currentTestSuite = null;
105 
106 		for( TestSuite testSuite : project.getTestSuiteList() )
107 		{
108 			if( !testSuite.isDisabled() )
109 			{
110 				testSuite.addTestSuiteRunListener( internalTestRunListener );
111 				notifyBeforeRunTestSuite( testSuite );
112 				runTestSuite( ( WsdlTestSuite )testSuite, true );
113 			}
114 		}
115 
116 		try
117 		{
118 			synchronized( activeRunners )
119 			{
120 				activeRunners.wait();
121 			}
122 		}
123 		catch( InterruptedException e )
124 		{
125 			e.printStackTrace();
126 		}
127 	}
128 
129 	private void runSequential( WsdlProject project, WsdlProjectRunContext runContext )
130 	{
131 		currentTestSuiteIndex = 0;
132 		for( ; isRunning() && currentTestSuiteIndex < project.getTestSuiteCount(); currentTestSuiteIndex++ )
133 		{
134 			currentTestSuite = ( WsdlTestSuite )project.getTestSuiteAt( currentTestSuiteIndex );
135 			if( !currentTestSuite.isDisabled() )
136 			{
137 				notifyBeforeRunTestSuite( currentTestSuite );
138 				WsdlTestSuiteRunner testSuiteRunner = runTestSuite( currentTestSuite, false );
139 				activeRunners.remove( testSuiteRunner );
140 				finishedRunners.add( testSuiteRunner );
141 				notifyAfterRunTestSuite( testSuiteRunner );
142 			}
143 		}
144 
145 		updateStatus();
146 	}
147 
148 	private void updateStatus()
149 	{
150 		for( TestSuiteRunner runner : finishedRunners )
151 		{
152 			if( runner.getStatus() == Status.FAILED )
153 			{
154 				setStatus( Status.FAILED );
155 				break;
156 			}
157 		}
158 	}
159 
160 	private WsdlTestSuiteRunner runTestSuite( WsdlTestSuite testSuite, boolean async )
161 	{
162 		DefaultPropertyExpansionContext properties = ( DefaultPropertyExpansionContext )getRunContext().getProperties();
163 		properties.put( "#TestSuiteRunner#", this );
164 
165 		WsdlTestSuiteRunner currentRunner = testSuite.run( properties, true );
166 		activeRunners.add( currentRunner );
167 		if( !async )
168 			currentRunner.waitUntilFinished();
169 
170 		return currentRunner;
171 	}
172 
173 	protected void internalFinally( WsdlProjectRunContext runContext )
174 	{
175 		WsdlProject project = getTestRunnable();
176 
177 		try
178 		{
179 			project.runAfterRunScript( runContext, this );
180 		}
181 		catch( Exception e )
182 		{
183 			SoapUI.logError( e );
184 		}
185 		
186 		notifyAfterRun();
187 
188 		runContext.clear();
189 		listeners = null;
190 	}
191 
192 	private void notifyAfterRun()
193 	{
194 		if( listeners == null || listeners.length == 0 )
195 			return;
196 
197 		for( int i = 0; i < listeners.length; i++ )
198 		{
199 			listeners[i].afterRun( this, getRunContext() );
200 		}
201 	}
202 
203 	private void notifyBeforeRun()
204 	{
205 		if( listeners == null || listeners.length == 0 )
206 			return;
207 
208 		for( int i = 0; i < listeners.length; i++ )
209 		{
210 			listeners[i].beforeRun( this, getRunContext() );
211 		}
212 	}
213 
214 	private void notifyAfterRunTestSuite( TestSuiteRunner testSuiteRunner )
215 	{
216 		if( listeners == null || listeners.length == 0 )
217 			return;
218 
219 		for( int i = 0; i < listeners.length; i++ )
220 		{
221 			listeners[i].afterTestSuite( this, getRunContext(), testSuiteRunner );
222 		}
223 	}
224 
225 	private void notifyBeforeRunTestSuite( TestSuite testSuite )
226 	{
227 		if( listeners == null || listeners.length == 0 )
228 			return;
229 
230 		for( int i = 0; i < listeners.length; i++ )
231 		{
232 			listeners[i].beforeTestSuite( this, getRunContext(), testSuite );
233 		}
234 	}
235 
236 	public List<TestSuiteRunner> getResults()
237 	{
238 		return Arrays.asList( finishedRunners.toArray( new TestSuiteRunner[finishedRunners.size()] ) );
239 	}
240 
241 	protected void finishRunner( TestSuiteRunner testRunner )
242 	{
243 		notifyAfterRunTestSuite( testRunner );
244 
245 		activeRunners.remove( testRunner );
246 		finishedRunners.add( testRunner );
247 
248 		testRunner.getTestSuite().removeTestSuiteRunListener( internalTestRunListener );
249 
250 		if( activeRunners.isEmpty() )
251 		{
252 			updateStatus();
253 			
254 			synchronized( activeRunners )
255 			{
256 				activeRunners.notify();
257 			}
258 		}
259 	}
260 
261 	private class InternalTestSuiteRunListener extends TestSuiteRunListenerAdapter
262 	{
263 		@Override
264 		public void afterRun( TestSuiteRunner testRunner, TestSuiteRunContext runContext )
265 		{
266 			finishRunner( testRunner );
267 		}
268 	}
269 
270 	public Project getProject()
271 	{
272 		return getTestRunnable();
273 	}
274 }