View Javadoc

1   /*
2    *  soapUI, copyright (C) 2004-2009 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  		project.runBeforeRunScript( runContext, this );
76  		if( !isRunning() )
77  			return;
78  
79  		if( project.getTimeout() > 0 )
80  		{
81  			startTimeoutTimer( project.getTimeout() );
82  		}
83  
84  		listeners = project.getProjectRunListeners();
85  		notifyBeforeRun();
86  		if( !isRunning() )
87  			return;
88  
89  		if( project.getRunType() == TestSuiteRunType.SEQUENTIAL )
90  		{
91  			runSequential( project, runContext );
92  		}
93  		else if( project.getRunType() == TestSuiteRunType.PARALLEL )
94  		{
95  			runParallel( project, runContext );
96  		}
97  	}
98  
99  	private void runParallel( WsdlProject project, WsdlProjectRunContext runContext )
100 	{
101 		currentTestSuiteIndex = -1;
102 		currentTestSuite = null;
103 
104 		for( TestSuite testSuite : project.getTestSuiteList() )
105 		{
106 			if( !testSuite.isDisabled() )
107 			{
108 				testSuite.addTestSuiteRunListener( internalTestRunListener );
109 				notifyBeforeRunTestSuite( testSuite );
110 				runTestSuite( ( WsdlTestSuite )testSuite, true );
111 			}
112 		}
113 
114 		try
115 		{
116 			synchronized( activeRunners )
117 			{
118 				activeRunners.wait();
119 			}
120 		}
121 		catch( InterruptedException e )
122 		{
123 			e.printStackTrace();
124 		}
125 	}
126 
127 	private void runSequential( WsdlProject project, WsdlProjectRunContext runContext )
128 	{
129 		currentTestSuiteIndex = 0;
130 		for( ; isRunning() && currentTestSuiteIndex < project.getTestSuiteCount(); currentTestSuiteIndex++ )
131 		{
132 			currentTestSuite = ( WsdlTestSuite )project.getTestSuiteAt( currentTestSuiteIndex );
133 			if( !currentTestSuite.isDisabled() )
134 			{
135 				notifyBeforeRunTestSuite( currentTestSuite );
136 				WsdlTestSuiteRunner testSuiteRunner = runTestSuite( currentTestSuite, false );
137 				activeRunners.remove( testSuiteRunner );
138 				finishedRunners.add( testSuiteRunner );
139 				notifyAfterRunTestSuite( testSuiteRunner );
140 			}
141 		}
142 
143 		updateStatus();
144 	}
145 
146 	private void updateStatus()
147 	{
148 		for( TestSuiteRunner runner : finishedRunners )
149 		{
150 			if( runner.getStatus() == Status.FAILED )
151 			{
152 				setStatus( Status.FAILED );
153 				break;
154 			}
155 		}
156 	}
157 
158 	private WsdlTestSuiteRunner runTestSuite( WsdlTestSuite testSuite, boolean async )
159 	{
160 		DefaultPropertyExpansionContext properties = ( DefaultPropertyExpansionContext )getRunContext().getProperties();
161 		properties.put( "#TestSuiteRunner#", this );
162 
163 		WsdlTestSuiteRunner currentRunner = testSuite.run( properties, true );
164 		activeRunners.add( currentRunner );
165 		if( !async )
166 			currentRunner.waitUntilFinished();
167 
168 		return currentRunner;
169 	}
170 
171 	protected void internalFinally( WsdlProjectRunContext runContext )
172 	{
173 		WsdlProject project = getTestRunnable();
174 
175 		try
176 		{
177 			project.runAfterRunScript( runContext, this );
178 		}
179 		catch( Exception e )
180 		{
181 			SoapUI.logError( e );
182 		}
183 		
184 		notifyAfterRun();
185 
186 		runContext.clear();
187 		listeners = null;
188 	}
189 
190 	private void notifyAfterRun()
191 	{
192 		if( listeners == null || listeners.length == 0 )
193 			return;
194 
195 		for( int i = 0; i < listeners.length; i++ )
196 		{
197 			listeners[i].afterRun( this, getRunContext() );
198 		}
199 	}
200 
201 	private void notifyBeforeRun()
202 	{
203 		if( listeners == null || listeners.length == 0 )
204 			return;
205 
206 		for( int i = 0; i < listeners.length; i++ )
207 		{
208 			listeners[i].beforeRun( this, getRunContext() );
209 		}
210 	}
211 
212 	private void notifyAfterRunTestSuite( TestSuiteRunner testSuiteRunner )
213 	{
214 		if( listeners == null || listeners.length == 0 )
215 			return;
216 
217 		for( int i = 0; i < listeners.length; i++ )
218 		{
219 			listeners[i].afterTestSuite( this, getRunContext(), testSuiteRunner );
220 		}
221 	}
222 
223 	private void notifyBeforeRunTestSuite( TestSuite testSuite )
224 	{
225 		if( listeners == null || listeners.length == 0 )
226 			return;
227 
228 		for( int i = 0; i < listeners.length; i++ )
229 		{
230 			listeners[i].beforeTestSuite( this, getRunContext(), testSuite );
231 		}
232 	}
233 
234 	public List<TestSuiteRunner> getResults()
235 	{
236 		return Arrays.asList( finishedRunners.toArray( new TestSuiteRunner[finishedRunners.size()] ) );
237 	}
238 
239 	protected void finishRunner( TestSuiteRunner testRunner )
240 	{
241 		notifyAfterRunTestSuite( testRunner );
242 
243 		activeRunners.remove( testRunner );
244 		finishedRunners.add( testRunner );
245 
246 		testRunner.getTestSuite().removeTestSuiteRunListener( internalTestRunListener );
247 
248 		if( activeRunners.isEmpty() )
249 		{
250 			updateStatus();
251 			
252 			synchronized( activeRunners )
253 			{
254 				activeRunners.notify();
255 			}
256 		}
257 	}
258 
259 	private class InternalTestSuiteRunListener extends TestSuiteRunListenerAdapter
260 	{
261 		@Override
262 		public void afterRun( TestSuiteRunner testRunner, TestSuiteRunContext runContext )
263 		{
264 			finishRunner( testRunner );
265 		}
266 	}
267 
268 	public Project getProject()
269 	{
270 		return getTestRunnable();
271 	}
272 }