View Javadoc

1   /*
2    *  soapUI, copyright (C) 2004-2007 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.teststeps;
14  
15  import java.beans.PropertyChangeEvent;
16  import java.beans.PropertyChangeListener;
17  import java.util.ArrayList;
18  import java.util.Collection;
19  
20  import javax.swing.ImageIcon;
21  
22  import org.apache.log4j.Logger;
23  
24  import com.eviware.soapui.config.CallConfig;
25  import com.eviware.soapui.config.RequestStepConfig;
26  import com.eviware.soapui.config.TestStepConfig;
27  import com.eviware.soapui.impl.wsdl.AbstractWsdlModelItem;
28  import com.eviware.soapui.impl.wsdl.WsdlInterface;
29  import com.eviware.soapui.impl.wsdl.WsdlOperation;
30  import com.eviware.soapui.impl.wsdl.WsdlRequest;
31  import com.eviware.soapui.impl.wsdl.WsdlSubmit;
32  import com.eviware.soapui.impl.wsdl.submit.filters.PropertyExpansionRequestFilter;
33  import com.eviware.soapui.impl.wsdl.submit.transports.http.WsdlResponse;
34  import com.eviware.soapui.impl.wsdl.support.assertions.Assertable.AssertionStatus;
35  import com.eviware.soapui.impl.wsdl.testcase.WsdlTestCase;
36  import com.eviware.soapui.impl.wsdl.teststeps.assertions.AssertionError;
37  import com.eviware.soapui.model.iface.Interface;
38  import com.eviware.soapui.model.iface.Operation;
39  import com.eviware.soapui.model.iface.Submit;
40  import com.eviware.soapui.model.iface.Request.SubmitException;
41  import com.eviware.soapui.model.project.Project;
42  import com.eviware.soapui.model.support.InterfaceListenerAdapter;
43  import com.eviware.soapui.model.support.ProjectListenerAdapter;
44  import com.eviware.soapui.model.support.TestStepBeanProperty;
45  import com.eviware.soapui.model.testsuite.TestRunContext;
46  import com.eviware.soapui.model.testsuite.TestRunner;
47  import com.eviware.soapui.model.testsuite.TestStepResult;
48  import com.eviware.soapui.model.testsuite.TestStepResult.TestStepStatus;
49  
50  /***
51   * WsdlTestStep that executes a WsdlTestRequest
52   * 
53   * @author Ole.Matzura
54   */
55  
56  public class WsdlTestRequestStep extends WsdlTestStep implements PropertyChangeListener 
57  {
58  	private final static Logger log = Logger.getLogger( WsdlTestRequestStep.class );
59     private RequestStepConfig requestStepConfig;
60     private WsdlTestRequest testRequest;
61  	private WsdlOperation wsdlOperation;
62  	private final InternalProjectListener projectListener = new InternalProjectListener();
63  	private final InternalInterfaceListener interfaceListener = new InternalInterfaceListener();
64  	private WsdlSubmit submit;
65  
66     public WsdlTestRequestStep(WsdlTestCase testCase, TestStepConfig config, boolean forLoadTest)
67     {
68        super( testCase, config, true, forLoadTest );
69        
70        if( getConfig().getConfig() != null )
71        {
72  			requestStepConfig = (RequestStepConfig) getConfig().getConfig().changeType(RequestStepConfig.type);
73           
74           wsdlOperation = findWsdlOperation();
75  			if( wsdlOperation == null )
76           {   
77              log.error( "Could not find operation [" + requestStepConfig.getOperation() + "] in interface [" + 
78              		requestStepConfig.getInterface() + "] for test request" );
79              requestStepConfig.setRequest(null);
80           }
81           else
82           {
83           	if( !forLoadTest )
84           	{
85  	         	wsdlOperation.getInterface().getProject().addProjectListener( projectListener );
86  	         	wsdlOperation.getInterface().addInterfaceListener( interfaceListener );
87  	         	
88  	         	// we need to listen for name changes which happen when interfaces are updated..
89  	         	wsdlOperation.getInterface().addPropertyChangeListener( this );
90  	         	wsdlOperation.addPropertyChangeListener( this );
91           	}
92           	
93              testRequest = new WsdlTestRequest( wsdlOperation, requestStepConfig.getRequest(), this, forLoadTest );
94              testRequest.addPropertyChangeListener( this );
95              
96              if( config.isSetName() )
97              	testRequest.setName( config.getName() );
98              else
99              	config.setName( testRequest.getName() );
100          }
101       }
102       else
103       {
104          requestStepConfig = (RequestStepConfig) getConfig().addNewConfig().changeType( RequestStepConfig.type );
105       }
106       
107       // init properties
108       addProperty( new TestStepBeanProperty( "Endpoint", false, testRequest, "endpoint", this ));
109       addProperty( new TestStepBeanProperty( "Username", false, testRequest, "username", this ));
110       addProperty( new TestStepBeanProperty( "Password", false, testRequest, "password", this ));
111       addProperty( new TestStepBeanProperty( "Domain", false, testRequest, "domain", this ));
112       addProperty( new TestStepBeanProperty( "Request", false, testRequest, "requestContent", this ));
113       addProperty( new TestStepBeanProperty( "Response", true, testRequest, "responseContent", this ));
114    }
115    
116 	public WsdlTestRequestStep(WsdlTestCase testCase, TestStepConfig testStep, WsdlRequest request)
117 	{
118 		this( testCase, testStep, false );
119 
120       requestStepConfig.setInterface( request.getOperation().getInterface().getName() );
121       requestStepConfig.setOperation( request.getOperation().getName() );
122 
123       CallConfig testRequestConfig = requestStepConfig.getRequest();
124       if( testRequestConfig == null ) testRequestConfig = requestStepConfig.addNewRequest();
125       
126       testRequestConfig.setName( request.getName() );
127       testRequestConfig.setEncoding( request.getEncoding() );
128       testRequestConfig.setEndpoint( request.getEndpoint() );
129       testRequestConfig.addNewRequest().setStringValue( request.getRequestContent() );
130       if( request.getConfig().getCredentials() != null )
131       	testRequestConfig.setCredentials( request.getConfig().getCredentials() );
132 
133       testRequest = new WsdlTestRequest( request.getOperation(), testRequestConfig, this, false );
134       request.copyAttachmentsTo( testRequest );
135 
136       testRequest.addPropertyChangeListener( this );
137       
138       wsdlOperation = findWsdlOperation();
139       if( wsdlOperation == null )
140       	throw new RuntimeException( "Failed to find operation [" + requestStepConfig.getOperation() + "] for test request" );
141       
142       wsdlOperation.getInterface().addInterfaceListener( interfaceListener );
143       wsdlOperation.getInterface().getProject().addProjectListener( projectListener );
144 	}
145 
146 	public WsdlTestRequestStep(WsdlTestCase testCase, WsdlTestRequest sourceRequest)
147 	{
148 		this( testCase, TestStepConfig.Factory.newInstance(), sourceRequest );
149 	}
150 	
151 	public WsdlTestStep clone( WsdlTestCase targetTestCase, String name)
152 	{
153 		onSave(); 
154 		
155 		TestStepConfig config = (TestStepConfig) getConfig().copy();
156 		RequestStepConfig stepConfig = (RequestStepConfig) config.getConfig().changeType(RequestStepConfig.type);
157 		
158 		while( stepConfig.getRequest().sizeOfAttachmentArray() > 0 )
159 			stepConfig.getRequest().removeAttachment( 0 );
160 		
161 		config.setName( name );
162 		stepConfig.getRequest().setName( name );
163 		
164 		WsdlTestRequestStep result = (WsdlTestRequestStep) targetTestCase.addTestStep( config );
165 		testRequest.copyAttachmentsTo( result.getTestRequest() );
166 		
167 		return result;
168 	}
169 	
170 	private WsdlOperation findWsdlOperation()
171    {
172    	WsdlTestCase testCase = (WsdlTestCase) getTestCase();
173    	if( testCase == null || testCase.getTestSuite() == null )
174    		return null;
175    	
176       Project project = testCase.getTestSuite().getProject();
177       WsdlOperation operation = null;
178       for( int c = 0; c < project.getInterfaceCount(); c++ )
179       {
180          if( project.getInterfaceAt( c ).getName().equals( requestStepConfig.getInterface()))
181          {
182             WsdlInterface iface = (WsdlInterface) project.getInterfaceAt( c );
183             for( int i = 0; i < iface.getOperationCount(); i++ )
184             {
185                if( iface.getOperationAt( i ).getName().equals( requestStepConfig.getOperation() ))
186                {
187                   operation = (WsdlOperation) iface.getOperationAt( i );
188                   break;
189                }
190             }
191             
192             if( operation != null )
193             	break;
194          }
195       }
196       return operation;
197    }
198 	
199 	public String getInterfaceName()
200 	{
201 		return requestStepConfig.getInterface();
202 	}
203 	
204 	public String getOperationName()
205 	{
206 		return requestStepConfig.getOperation();
207 	}
208 
209 	public void release()
210 	{
211 		super.release();
212 		
213 		if( wsdlOperation == null )
214 			wsdlOperation = findWsdlOperation();
215 		
216       if( wsdlOperation != null )
217       {
218 	      wsdlOperation.removePropertyChangeListener( this );
219 	     	wsdlOperation.getInterface().getProject().removeProjectListener( projectListener );
220 	     	wsdlOperation.getInterface().removeInterfaceListener( interfaceListener );
221 	     	wsdlOperation.getInterface().removePropertyChangeListener( this );
222       }
223       
224       testRequest.removePropertyChangeListener( this );
225       testRequest.release();
226 	}
227 
228 	public void resetConfigOnMove(TestStepConfig config)
229 	{
230 		super.resetConfigOnMove(config);
231 
232 		requestStepConfig = (RequestStepConfig) config.getConfig().changeType(RequestStepConfig.type);
233 		testRequest.updateConfig( requestStepConfig.getRequest() );
234 	}
235 
236 	public ImageIcon getIcon()
237    {
238       return testRequest.getIcon();
239    }
240 
241    public String getName()
242    {
243       return testRequest == null ? super.getName() : testRequest.getName();
244    }
245    
246    public WsdlTestRequest getTestRequest()
247    {
248       return testRequest;
249    }
250    
251 	public void setName(String name)
252 	{
253 		testRequest.setName( name );
254 		super.setName( name );
255 	}
256 
257    public void propertyChange(PropertyChangeEvent arg0) 
258    {
259    	if( arg0.getSource() == wsdlOperation )
260    	{
261    		if( arg0.getPropertyName().equals( Operation.NAME_PROPERTY ))
262    		{
263    			requestStepConfig.setOperation( (String) arg0.getNewValue() );
264    		}
265    	}
266    	else if( arg0.getSource() == wsdlOperation.getInterface() )
267    	{
268    		if( arg0.getPropertyName().equals( Interface.NAME_PROPERTY ))
269    		{
270    			requestStepConfig.setInterface( (String) arg0.getNewValue() );
271    		}
272    	}
273    	else
274    	{
275    	   notifyPropertyChanged( arg0.getPropertyName(), arg0.getOldValue(), arg0.getNewValue());
276    	}
277    }
278 
279 	public TestStepResult run( TestRunner runner, TestRunContext runContext ) 
280 	{
281 		WsdlTestRequestStepResult testStepResult = new WsdlTestRequestStepResult(this);
282 		
283    	try
284 		{
285 			submit = testRequest.submit( runContext, false );
286 			WsdlResponse response = (WsdlResponse) submit.getResponse();
287 			
288 			if( submit.getStatus() != Submit.Status.CANCELED )
289 			{
290 				if( submit.getStatus() == Submit.Status.ERROR )
291 				{
292 					testStepResult.setStatus( TestStepStatus.FAILED );
293 					testStepResult.addMessage( submit.getError().toString() );
294 					
295 					testRequest.setResponse( null, runContext );
296 				}
297 				else if( response == null )
298 				{
299 					testStepResult.setStatus( TestStepStatus.FAILED );
300 					testStepResult.addMessage( "Request is missing response" );
301 					
302 					testRequest.setResponse( null, runContext );
303 				}
304 				else
305 				{
306 					testRequest.setResponse( response, runContext );
307 					
308 					testStepResult.setTimeTaken( response.getTimeTaken() );
309 			   	testStepResult.setSize( response.getContentLength() );
310 			   	testStepResult.setResponse( response );
311 			   	
312 			   	switch( testRequest.getAssertionStatus() )
313 			   	{
314 			   		case FAILED : testStepResult.setStatus( TestStepStatus.FAILED); break; 
315 			   		case VALID : testStepResult.setStatus( TestStepStatus.OK); break; 
316 			   		case UNKNOWN : testStepResult.setStatus( TestStepStatus.UNKNOWN); break; 
317 			   	}
318 				}
319 			}
320 			else
321 			{
322 				testStepResult.setStatus( TestStepStatus.CANCELED );
323 				testStepResult.addMessage( "Request was canceled" );
324 			}
325 			
326 			if( response != null )
327 				testStepResult.setRequestContent( response.getRequestContent() );
328 			else
329 				testStepResult.setRequestContent( testRequest.getRequestContent() );
330 		}
331 		catch (SubmitException e)
332 		{
333 			testStepResult.setStatus( TestStepStatus.FAILED );
334 			testStepResult.addMessage( "SubmitException: " + e );
335 		}
336 		finally
337 		{
338 			submit = null;
339 		}
340 		
341 		testStepResult.setDomain( testRequest.getDomain() );
342 		testStepResult.setUsername( testRequest.getUsername() );
343 		testStepResult.setPassword( testRequest.getPassword() );
344 		testStepResult.setEndpoint( PropertyExpansionRequestFilter.expandProperties( runContext, 
345 					testRequest.getEndpoint() ));
346 		testStepResult.setEncoding( testRequest.getEncoding() );
347    	
348 		if( testStepResult.getStatus() != TestStepStatus.CANCELED )
349 		{
350 	   	AssertionStatus assertionStatus = testRequest.getAssertionStatus();
351 			switch( assertionStatus )
352 	   	{
353 	   		case FAILED : 
354 				{
355 					testStepResult.setStatus( TestStepStatus.FAILED );
356 					if( getAssertionCount() == 0 )
357 					{
358 						testStepResult.addMessage( "Invalid/empty response" );
359 					}
360 					else for( int c = 0; c < getAssertionCount(); c++ )
361 					{
362 						AssertionError[] errors = getAssertionAt( c ).getErrors();
363 						if( errors != null )
364 						{
365 							for( AssertionError error : errors )
366 							{
367 								testStepResult.addMessage( error.getMessage() );
368 							}
369 						}
370 					}
371 					
372 					break;
373 				}
374 	   	//	default : testStepResult.setStatus( TestStepStatus.OK ); break;
375 	   	}
376 		}
377    	
378 		return testStepResult;
379 	}
380 	
381 	public WsdlMessageAssertion getAssertionAt(int index)
382 	{
383 		return testRequest.getAssertionAt( index );
384 	}
385 
386 	public int getAssertionCount()
387 	{
388 		return testRequest.getAssertionCount();
389 	}
390 	
391 	public class InternalProjectListener extends ProjectListenerAdapter 
392 	{
393 		public void interfaceRemoved(Interface iface)
394 		{
395 			if( wsdlOperation != null && wsdlOperation.getInterface().equals( iface ))
396 			{
397 				log.debug( "Removing test step due to removed interface" );
398 				((WsdlTestCase)getTestCase()).removeTestStep( WsdlTestRequestStep.this );
399 			}
400 		}
401 	}
402 
403 	public class InternalInterfaceListener extends InterfaceListenerAdapter
404 	{
405 		@Override
406 		public void operationRemoved(Operation operation)
407 		{
408 			if( operation == wsdlOperation )
409 			{
410 				log.debug( "Removing test step due to removed operation" );
411 				((WsdlTestCase)getTestCase()).removeTestStep( WsdlTestRequestStep.this );
412 			}
413 		}
414 
415 		@Override
416 		public void operationUpdated( Operation operation )
417 		{
418 			if( operation == wsdlOperation )
419 			{
420 				requestStepConfig.setOperation( operation.getName() );
421 			}
422 		}
423 	}
424 	
425 	public boolean cancel()
426 	{
427 		if( submit == null )
428 			return false;
429 		
430 		submit.cancel();
431 		
432 		return true;
433 	}
434 
435 	@Override
436 	public Collection<WsdlInterface> getRequiredInterfaces()
437 	{
438 		ArrayList<WsdlInterface> result = new ArrayList<WsdlInterface>( );
439 		result.add( findWsdlOperation().getInterface() );
440 		return result;
441 	}
442 
443 	public boolean dependsOn( AbstractWsdlModelItem modelItem )
444 	{
445 		if( modelItem instanceof Interface && testRequest.getOperation().getInterface() == modelItem )
446 		{
447 			return true;
448 		}
449 		else if( modelItem instanceof Operation && testRequest.getOperation() == modelItem )
450 		{
451 			return true;
452 		}
453 		
454 		return false;
455 	}
456 
457 	@Override
458 	public void onSave()
459 	{
460 		testRequest.onSave();
461 	}
462 
463 	public String getDescription()
464 	{
465 		return testRequest.getDescription();
466 	}
467 
468 	public void setDescription( String description )
469 	{
470 		testRequest.setDescription( description );
471 	}
472 
473 	public void setOperation( WsdlOperation operation )
474 	{
475 		if( wsdlOperation == operation )
476 			return;
477 		
478 		WsdlOperation oldOperation = wsdlOperation;
479 		wsdlOperation = operation;
480 		requestStepConfig.setInterface( operation.getInterface().getName() );
481 		requestStepConfig.setOperation( operation.getName() );
482 		
483 		oldOperation.removePropertyChangeListener( this );
484 		wsdlOperation.addPropertyChangeListener( this );
485 		
486 		testRequest.setOperation( wsdlOperation );
487 	}
488 }