View Javadoc

1   /*
2    *  soapUI, copyright (C) 2004-2008 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 com.eviware.soapui.config.RequestStepConfig;
16  import com.eviware.soapui.config.TestStepConfig;
17  import com.eviware.soapui.impl.wsdl.*;
18  import com.eviware.soapui.impl.wsdl.submit.transports.http.WsdlResponse;
19  import com.eviware.soapui.impl.wsdl.support.assertions.AssertedXPathsContainer;
20  import com.eviware.soapui.impl.wsdl.testcase.WsdlTestCase;
21  import com.eviware.soapui.impl.wsdl.testcase.WsdlTestRunContext;
22  import com.eviware.soapui.impl.wsdl.teststeps.assertions.TestAssertionRegistry.AssertableType;
23  import com.eviware.soapui.model.ModelItem;
24  import com.eviware.soapui.model.iface.Interface;
25  import com.eviware.soapui.model.iface.Operation;
26  import com.eviware.soapui.model.iface.Request.SubmitException;
27  import com.eviware.soapui.model.iface.Submit;
28  import com.eviware.soapui.model.project.Project;
29  import com.eviware.soapui.model.propertyexpansion.PropertyExpansion;
30  import com.eviware.soapui.model.propertyexpansion.PropertyExpansionContainer;
31  import com.eviware.soapui.model.propertyexpansion.PropertyExpansionUtils;
32  import com.eviware.soapui.model.propertyexpansion.PropertyExpansionsResult;
33  import com.eviware.soapui.model.support.InterfaceListenerAdapter;
34  import com.eviware.soapui.model.support.ProjectListenerAdapter;
35  import com.eviware.soapui.model.support.TestStepBeanProperty;
36  import com.eviware.soapui.model.testsuite.*;
37  import com.eviware.soapui.model.testsuite.AssertionError;
38  import com.eviware.soapui.model.testsuite.TestStepResult.TestStepStatus;
39  import com.eviware.soapui.support.resolver.ChangeOperationResolver;
40  import com.eviware.soapui.support.resolver.ImportInterfaceResolver;
41  import com.eviware.soapui.support.resolver.ResolveContext;
42  import com.eviware.soapui.support.resolver.defaultaction.RemoveTestStepDefaultResolveAction;
43  import com.eviware.soapui.support.types.StringToStringMap;
44  import org.apache.log4j.Logger;
45  
46  import javax.swing.*;
47  import java.beans.PropertyChangeEvent;
48  import java.beans.PropertyChangeListener;
49  import java.util.*;
50  
51  /***
52   * WsdlTestStep that executes a WsdlTestRequest
53   *
54   * @author Ole.Matzura
55   */
56  
57  public class WsdlTestRequestStep extends WsdlTestStepWithProperties implements OperationTestStep,
58          PropertyChangeListener, PropertyExpansionContainer, Assertable
59  {
60     private final static Logger log = Logger.getLogger( WsdlTestRequestStep.class );
61     private RequestStepConfig requestStepConfig;
62     private WsdlTestRequest testRequest;
63     private WsdlOperation wsdlOperation;
64     private final InternalProjectListener projectListener = new InternalProjectListener();
65     private final InternalInterfaceListener interfaceListener = new InternalInterfaceListener();
66     private WsdlSubmit<WsdlRequest> submit;
67  
68     public WsdlTestRequestStep( WsdlTestCase testCase, TestStepConfig config, boolean forLoadTest )
69     {
70        super( testCase, config, true, forLoadTest );
71  
72        if( getConfig().getConfig() != null )
73        {
74           requestStepConfig = (RequestStepConfig) getConfig().getConfig().changeType( RequestStepConfig.type );
75  
76           wsdlOperation = findWsdlOperation();
77           if( wsdlOperation == null )
78           {
79              log.error( "Could not find operation [" + requestStepConfig.getOperation() + "] in interface ["
80                      + requestStepConfig.getInterface() + "] for test request [" + getName() + "] in TestCase ["
81                      + getTestCase().getTestSuite().getName() + "/" + getTestCase().getName() + "]" );
82  //				requestStepConfig.setRequest(null);
83              setDisabled( true );
84           }
85           else
86           {
87              initTestRequest( config, forLoadTest );
88           }
89        }
90        else
91        {
92           requestStepConfig = (RequestStepConfig) getConfig().addNewConfig().changeType( RequestStepConfig.type );
93        }
94  
95        // init properties
96        if( testRequest != null )
97        {
98           initRequestProperties();
99        }
100    }
101 
102    private void initRequestProperties()
103    {
104       addProperty( new TestStepBeanProperty( "Endpoint", false, testRequest, "endpoint", this ) );
105       addProperty( new TestStepBeanProperty( "Username", false, testRequest, "username", this ) );
106       addProperty( new TestStepBeanProperty( "Password", false, testRequest, "password", this ) );
107       addProperty( new TestStepBeanProperty( "Domain", false, testRequest, "domain", this ) );
108       addProperty( new TestStepBeanProperty( "Request", false, testRequest, "requestContent", this )
109       {
110          @Override
111          public String getDefaultValue()
112          {
113             return getOperation().createRequest( true );
114          }
115       } );
116       addProperty( new TestStepBeanProperty( "Response", true, testRequest, "responseContent", this )
117       {
118          @Override
119          public String getDefaultValue()
120          {
121             return getOperation().createResponse( true );
122          }
123       } );
124    }
125 
126    private void initTestRequest( TestStepConfig config, boolean forLoadTest )
127    {
128       if( !forLoadTest )
129       {
130          wsdlOperation.getInterface().getProject().addProjectListener( projectListener );
131          wsdlOperation.getInterface().addInterfaceListener( interfaceListener );
132 
133          // we need to listen for name changes which happen when
134          // interfaces are updated..
135          wsdlOperation.getInterface().addPropertyChangeListener( this );
136          wsdlOperation.addPropertyChangeListener( this );
137       }
138 
139       testRequest = new WsdlTestRequest( wsdlOperation, requestStepConfig.getRequest(), this, forLoadTest );
140       testRequest.addPropertyChangeListener( this );
141 
142       if( config.isSetName() )
143          testRequest.setName( config.getName() );
144       else
145          config.setName( testRequest.getName() );
146    }
147 
148    @Override
149    public WsdlTestStep clone( WsdlTestCase targetTestCase, String name )
150    {
151       beforeSave();
152 
153       TestStepConfig config = (TestStepConfig) getConfig().copy();
154       RequestStepConfig stepConfig = (RequestStepConfig) config.getConfig().changeType( RequestStepConfig.type );
155 
156       while( stepConfig.getRequest().sizeOfAttachmentArray() > 0 )
157          stepConfig.getRequest().removeAttachment( 0 );
158 
159       config.setName( name );
160       stepConfig.getRequest().setName( name );
161 
162       WsdlTestRequestStep result = (WsdlTestRequestStep) targetTestCase.addTestStep( config );
163       testRequest.copyAttachmentsTo( result.getTestRequest() );
164 
165       return result;
166    }
167 
168    private WsdlOperation findWsdlOperation()
169    {
170       WsdlTestCase testCase = getTestCase();
171       if( testCase == null || testCase.getTestSuite() == null )
172          return null;
173 
174       Project project = testCase.getTestSuite().getProject();
175       WsdlOperation operation = null;
176       for( int c = 0; c < project.getInterfaceCount(); c++ )
177       {
178          if( project.getInterfaceAt( c ).getName().equals( requestStepConfig.getInterface() ) )
179          {
180             WsdlInterface iface = (WsdlInterface) project.getInterfaceAt( c );
181             for( int i = 0; i < iface.getOperationCount(); i++ )
182             {
183                if( iface.getOperationAt( i ).getName().equals( requestStepConfig.getOperation() ) )
184                {
185                   operation = iface.getOperationAt( i );
186                   break;
187                }
188             }
189 
190             if( operation != null )
191                break;
192          }
193       }
194       return operation;
195    }
196 
197    public String getInterfaceName()
198    {
199       return requestStepConfig.getInterface();
200    }
201 
202    public String getOperationName()
203    {
204       return requestStepConfig.getOperation();
205    }
206 
207    @Override
208    public void release()
209    {
210       super.release();
211 
212       if( wsdlOperation == null )
213          wsdlOperation = findWsdlOperation();
214 
215       if( wsdlOperation != null )
216       {
217          wsdlOperation.removePropertyChangeListener( this );
218          wsdlOperation.getInterface().getProject().removeProjectListener( projectListener );
219          wsdlOperation.getInterface().removeInterfaceListener( interfaceListener );
220          wsdlOperation.getInterface().removePropertyChangeListener( this );
221       }
222 
223       // could be null if initialization failed..
224       if( testRequest != null )
225       {
226          testRequest.removePropertyChangeListener( this );
227          testRequest.release();
228       }
229    }
230 
231    @Override
232    public void resetConfigOnMove( TestStepConfig config )
233    {
234       super.resetConfigOnMove( config );
235 
236       requestStepConfig = (RequestStepConfig) config.getConfig().changeType( RequestStepConfig.type );
237       testRequest.updateConfig( requestStepConfig.getRequest() );
238    }
239 
240    @Override
241    public ImageIcon getIcon()
242    {
243       return testRequest == null ? null : testRequest.getIcon();
244    }
245 
246    public WsdlTestRequest getTestRequest()
247    {
248       return testRequest;
249    }
250 
251    @Override
252    public void setName( String name )
253    {
254       super.setName( name );
255       testRequest.setName( name );
256    }
257 
258    public void propertyChange( PropertyChangeEvent arg0 )
259    {
260       if( arg0.getSource() == wsdlOperation )
261       {
262          if( arg0.getPropertyName().equals( Operation.NAME_PROPERTY ) )
263          {
264             requestStepConfig.setOperation( (String) arg0.getNewValue() );
265          }
266       }
267       else if( arg0.getSource() == wsdlOperation.getInterface() )
268       {
269          if( arg0.getPropertyName().equals( Interface.NAME_PROPERTY ) )
270          {
271             requestStepConfig.setInterface( (String) arg0.getNewValue() );
272          }
273       }
274       else if( arg0.getPropertyName().equals( TestAssertion.CONFIGURATION_PROPERTY )
275               || arg0.getPropertyName().equals( TestAssertion.DISABLED_PROPERTY ) )
276       {
277          if( getTestRequest().getResponse() != null )
278          {
279             getTestRequest().assertResponse( new WsdlTestRunContext( this ) );
280          }
281       }
282       else
283       {
284          if( arg0.getSource() == testRequest && arg0.getPropertyName().equals( WsdlTestRequest.NAME_PROPERTY ) )
285          {
286             if( !super.getName().equals( (String) arg0.getNewValue() ) )
287                super.setName( (String) arg0.getNewValue() );
288          }
289 
290          notifyPropertyChanged( arg0.getPropertyName(), arg0.getOldValue(), arg0.getNewValue() );
291       }
292    }
293 
294    public TestStepResult run( TestRunner runner, TestRunContext runContext )
295    {
296       WsdlTestRequestStepResult testStepResult = new WsdlTestRequestStepResult( this );
297 
298       try
299       {
300          submit = testRequest.submit( runContext, false );
301          WsdlResponse response = (WsdlResponse) submit.getResponse();
302 
303          if( submit.getStatus() != Submit.Status.CANCELED )
304          {
305             if( submit.getStatus() == Submit.Status.ERROR )
306             {
307                testStepResult.setStatus( TestStepStatus.FAILED );
308                testStepResult.addMessage( submit.getError().toString() );
309 
310                testRequest.setResponse( null, runContext );
311             }
312             else if( response == null )
313             {
314                testStepResult.setStatus( TestStepStatus.FAILED );
315                testStepResult.addMessage( "Request is missing response" );
316 
317                testRequest.setResponse( null, runContext );
318             }
319             else
320             {
321                runContext.setProperty( AssertedXPathsContainer.ASSERTEDXPATHSCONTAINER_PROPERTY, testStepResult );
322                testRequest.setResponse( response, runContext );
323 
324                testStepResult.setTimeTaken( response.getTimeTaken() );
325                testStepResult.setSize( response.getContentLength() );
326                testStepResult.setResponse( response );
327 
328                switch( testRequest.getAssertionStatus() )
329                {
330                   case FAILED:
331                      testStepResult.setStatus( TestStepStatus.FAILED );
332                      break;
333                   case VALID:
334                      testStepResult.setStatus( TestStepStatus.OK );
335                      break;
336                   case UNKNOWN:
337                      testStepResult.setStatus( TestStepStatus.UNKNOWN );
338                      break;
339                }
340             }
341          }
342          else
343          {
344             testStepResult.setStatus( TestStepStatus.CANCELED );
345             testStepResult.addMessage( "Request was canceled" );
346          }
347 
348          if( response != null )
349             testStepResult.setRequestContent( response.getRequestContent() );
350          else
351             testStepResult.setRequestContent( testRequest.getRequestContent() );
352       }
353       catch( SubmitException e )
354       {
355          testStepResult.setStatus( TestStepStatus.FAILED );
356          testStepResult.addMessage( "SubmitException: " + e );
357       }
358       finally
359       {
360          submit = null;
361       }
362 
363       testStepResult.setDomain( PropertyExpansionUtils.expandProperties( runContext, testRequest.getDomain() ) );
364       testStepResult.setUsername( PropertyExpansionUtils.expandProperties( runContext, testRequest.getUsername() ) );
365       testStepResult.setPassword( PropertyExpansionUtils.expandProperties( runContext, testRequest.getPassword() ) );
366       testStepResult.setEndpoint( PropertyExpansionUtils.expandProperties( runContext, testRequest.getEndpoint() ) );
367       testStepResult.setEncoding( PropertyExpansionUtils.expandProperties( runContext, testRequest.getEncoding() ) );
368 
369       if( testStepResult.getStatus() != TestStepStatus.CANCELED )
370       {
371          AssertionStatus assertionStatus = testRequest.getAssertionStatus();
372          switch( assertionStatus )
373          {
374             case FAILED:
375             {
376                testStepResult.setStatus( TestStepStatus.FAILED );
377                if( getAssertionCount() == 0 )
378                {
379                   testStepResult.addMessage( "Invalid/empty response" );
380                }
381                else
382                   for( int c = 0; c < getAssertionCount(); c++ )
383                   {
384                      AssertionError[] errors = getAssertionAt( c ).getErrors();
385                      if( errors != null )
386                      {
387                         for( AssertionError error : errors )
388                         {
389                            testStepResult.addMessage( error.getMessage() );
390                         }
391                      }
392                   }
393 
394                break;
395             }
396             // default : testStepResult.setStatus( TestStepStatus.OK ); break;
397          }
398       }
399 
400       return testStepResult;
401    }
402 
403    public WsdlMessageAssertion getAssertionAt( int index )
404    {
405       return testRequest.getAssertionAt( index );
406    }
407 
408    public int getAssertionCount()
409    {
410       return testRequest == null ? 0 : testRequest.getAssertionCount();
411    }
412 
413    public class InternalProjectListener extends ProjectListenerAdapter
414    {
415       @Override
416       public void interfaceRemoved( Interface iface )
417       {
418          if( wsdlOperation != null && wsdlOperation.getInterface().equals( iface ) )
419          {
420             log.debug( "Removing test step due to removed interface" );
421             ( getTestCase() ).removeTestStep( WsdlTestRequestStep.this );
422          }
423       }
424    }
425 
426    public class InternalInterfaceListener extends InterfaceListenerAdapter
427    {
428       @Override
429       public void operationRemoved( Operation operation )
430       {
431          if( operation == wsdlOperation )
432          {
433             log.debug( "Removing test step due to removed operation" );
434             ( getTestCase() ).removeTestStep( WsdlTestRequestStep.this );
435          }
436       }
437 
438       @Override
439       public void operationUpdated( Operation operation )
440       {
441          if( operation == wsdlOperation )
442          {
443             requestStepConfig.setOperation( operation.getName() );
444          }
445       }
446    }
447 
448    @Override
449    public boolean cancel()
450    {
451       if( submit == null )
452          return false;
453 
454       submit.cancel();
455 
456       return true;
457    }
458 
459    @Override
460    public Collection<WsdlInterface> getRequiredInterfaces()
461    {
462       ArrayList<WsdlInterface> result = new ArrayList<WsdlInterface>();
463       result.add( findWsdlOperation().getInterface() );
464       return result;
465    }
466 
467    public String getDefaultSourcePropertyName()
468    {
469       return "Response";
470    }
471 
472    public String getDefaultTargetPropertyName()
473    {
474       return "Request";
475    }
476 
477    @Override
478    public boolean dependsOn( AbstractWsdlModelItem<?> modelItem )
479    {
480       if( modelItem instanceof Interface && testRequest.getOperation().getInterface() == modelItem )
481       {
482          return true;
483       }
484       else if( modelItem instanceof Operation && testRequest.getOperation() == modelItem )
485       {
486          return true;
487       }
488 
489       return false;
490    }
491 
492    @Override
493    public void beforeSave()
494    {
495       super.beforeSave();
496 
497       if( testRequest != null )
498          testRequest.beforeSave();
499    }
500 
501    @Override
502    public String getDescription()
503    {
504       return testRequest == null ? "<missing>" : testRequest.getDescription();
505    }
506 
507    @Override
508    public void setDescription( String description )
509    {
510       if( testRequest != null )
511          testRequest.setDescription( description );
512    }
513 
514    public void setOperation( WsdlOperation operation )
515    {
516       if( wsdlOperation == operation )
517          return;
518 
519       WsdlOperation oldOperation = wsdlOperation;
520       wsdlOperation = operation;
521       requestStepConfig.setInterface( operation.getInterface().getName() );
522       requestStepConfig.setOperation( operation.getName() );
523 
524       if( oldOperation != null )
525          oldOperation.removePropertyChangeListener( this );
526 
527       wsdlOperation.addPropertyChangeListener( this );
528 
529       testRequest.setOperation( wsdlOperation );
530    }
531 
532    @Override
533    public List<? extends ModelItem> getChildren()
534    {
535       return testRequest == null ? Collections.EMPTY_LIST : testRequest.getAssertionList();
536    }
537 
538    public PropertyExpansion[] getPropertyExpansions()
539    {
540       PropertyExpansionsResult result = new PropertyExpansionsResult( this, testRequest );
541 
542       result.extractAndAddAll( "requestContent" );
543       result.extractAndAddAll( "endpoint" );
544       result.extractAndAddAll( "username" );
545       result.extractAndAddAll( "password" );
546       result.extractAndAddAll( "domain" );
547 
548       StringToStringMap requestHeaders = testRequest.getRequestHeaders();
549       for( String key : requestHeaders.keySet() )
550       {
551          result.extractAndAddAll( new RequestHeaderHolder( requestHeaders, key ), "value" );
552       }
553 
554       // result.addAll( testRequest.getWssContainer().getPropertyExpansions() );
555 
556       return result.toArray( new PropertyExpansion[result.size()] );
557    }
558 
559    public class RequestHeaderHolder
560    {
561       private final StringToStringMap valueMap;
562       private final String key;
563 
564       public RequestHeaderHolder( StringToStringMap valueMap, String key )
565       {
566          this.valueMap = valueMap;
567          this.key = key;
568       }
569 
570       public String getValue()
571       {
572          return valueMap.get( key );
573       }
574 
575       public void setValue( String value )
576       {
577          valueMap.put( key, value );
578          testRequest.setRequestHeaders( valueMap );
579       }
580    }
581 
582    public TestAssertion addAssertion( String type )
583    {
584       WsdlMessageAssertion result = testRequest.addAssertion( type );
585       return result;
586    }
587 
588    public void addAssertionsListener( AssertionsListener listener )
589    {
590       testRequest.addAssertionsListener( listener );
591    }
592 
593    public TestAssertion cloneAssertion( TestAssertion source, String name )
594    {
595       return testRequest.cloneAssertion( source, name );
596    }
597 
598    public String getAssertableContent()
599    {
600       return testRequest.getAssertableContent();
601    }
602 
603    public AssertableType getAssertableType()
604    {
605       return testRequest.getAssertableType();
606    }
607 
608    public TestAssertion getAssertionByName( String name )
609    {
610       return testRequest.getAssertionByName( name );
611    }
612 
613    public List<TestAssertion> getAssertionList()
614    {
615       return testRequest.getAssertionList();
616    }
617 
618    public AssertionStatus getAssertionStatus()
619    {
620       return testRequest.getAssertionStatus();
621    }
622 
623    public Interface getInterface()
624    {
625       return getOperation().getInterface();
626    }
627 
628    public WsdlOperation getOperation()
629    {
630       return wsdlOperation;
631    }
632 
633    public TestStep getTestStep()
634    {
635       return this;
636    }
637 
638    public void removeAssertion( TestAssertion assertion )
639    {
640       testRequest.removeAssertion( assertion );
641    }
642 
643    public void removeAssertionsListener( AssertionsListener listener )
644    {
645       testRequest.removeAssertionsListener( listener );
646    }
647 
648    public Map<String, TestAssertion> getAssertions()
649    {
650       return testRequest.getAssertions();
651    }
652 
653    @Override
654    public void prepare( TestRunner testRunner, TestRunContext testRunContext ) throws Exception
655    {
656       super.prepare( testRunner, testRunContext );
657 
658       for( TestAssertion assertion : testRequest.getAssertionList() )
659       {
660          assertion.prepare( testRunner, testRunContext );
661       }
662    }
663 
664    public String getDefaultAssertableContent()
665    {
666       return testRequest.getDefaultAssertableContent();
667    }
668 
669    @SuppressWarnings( "unchecked" )
670    public void resolve( ResolveContext context )
671    {
672       super.resolve( context );
673 
674       if( wsdlOperation == null )
675       {
676          context.addPathToResolve( this, "Missing SOAP Operation in Project",
677                  requestStepConfig.getInterface() + "/" + requestStepConfig.getOperation(),
678                  new RemoveTestStepDefaultResolveAction() ).addResolvers( new ImportInterfaceResolver( this )
679          {
680 
681             @Override
682             protected boolean update()
683             {
684                wsdlOperation = findWsdlOperation();
685                if( wsdlOperation == null )
686                   return false;
687 
688                initTestRequest( getConfig(), false );
689                initRequestProperties();
690                setDisabled( false );
691                return true;
692             }
693          },
694                  new ChangeOperationResolver( this )
695                  {
696 
697                     @Override
698                     public boolean update()
699                     {
700                        wsdlOperation = (WsdlOperation) getPickedOperation();
701                        if( wsdlOperation == null )
702                           return false;
703 
704                        initTestRequest( getConfig(), false );
705                        initRequestProperties();
706                        setDisabled( false );
707                        return true;
708                     }
709 
710                  } );
711       }
712       else
713       {
714          testRequest.resolve( context );
715       }
716    }
717 }