1
2
3
4
5
6
7
8
9
10
11
12
13 package com.eviware.soapui.impl.wsdl.teststeps;
14
15 import java.beans.PropertyChangeEvent;
16 import java.util.Collections;
17 import java.util.List;
18 import java.util.Map;
19
20 import javax.swing.ImageIcon;
21 import javax.xml.namespace.QName;
22
23 import org.apache.log4j.Logger;
24
25 import com.eviware.soapui.config.HttpRequestConfig;
26 import com.eviware.soapui.config.RequestStepConfig;
27 import com.eviware.soapui.config.TestStepConfig;
28 import com.eviware.soapui.impl.rest.support.RestParamProperty;
29 import com.eviware.soapui.impl.rest.support.RestRequestConverter;
30 import com.eviware.soapui.impl.support.AbstractHttpRequest;
31 import com.eviware.soapui.impl.support.http.HttpRequest;
32 import com.eviware.soapui.impl.wsdl.AbstractWsdlModelItem;
33 import com.eviware.soapui.impl.wsdl.WsdlSubmit;
34 import com.eviware.soapui.impl.wsdl.submit.transports.http.HttpResponse;
35 import com.eviware.soapui.impl.wsdl.support.assertions.AssertedXPathsContainer;
36 import com.eviware.soapui.impl.wsdl.testcase.WsdlTestCase;
37 import com.eviware.soapui.impl.wsdl.testcase.WsdlTestRunContext;
38 import com.eviware.soapui.impl.wsdl.teststeps.assertions.TestAssertionRegistry.AssertableType;
39 import com.eviware.soapui.model.ModelItem;
40 import com.eviware.soapui.model.iface.Interface;
41 import com.eviware.soapui.model.iface.Submit;
42 import com.eviware.soapui.model.iface.Request.SubmitException;
43 import com.eviware.soapui.model.propertyexpansion.PropertyExpander;
44 import com.eviware.soapui.model.propertyexpansion.PropertyExpansion;
45 import com.eviware.soapui.model.propertyexpansion.PropertyExpansionsResult;
46 import com.eviware.soapui.model.support.TestPropertyListenerAdapter;
47 import com.eviware.soapui.model.support.TestStepBeanProperty;
48 import com.eviware.soapui.model.testsuite.AssertionError;
49 import com.eviware.soapui.model.testsuite.AssertionsListener;
50 import com.eviware.soapui.model.testsuite.TestAssertion;
51 import com.eviware.soapui.model.testsuite.TestCaseRunContext;
52 import com.eviware.soapui.model.testsuite.TestCaseRunner;
53 import com.eviware.soapui.model.testsuite.TestProperty;
54 import com.eviware.soapui.model.testsuite.TestStep;
55 import com.eviware.soapui.model.testsuite.TestStepProperty;
56 import com.eviware.soapui.model.testsuite.TestStepResult;
57 import com.eviware.soapui.model.testsuite.TestStepResult.TestStepStatus;
58 import com.eviware.soapui.support.resolver.ResolveContext;
59 import com.eviware.soapui.support.types.StringToStringMap;
60
61 public class HttpTestRequestStep extends WsdlTestStepWithProperties implements HttpTestRequestStepInterface
62 {
63 @SuppressWarnings("unused")
64 private final static Logger log = Logger.getLogger( HttpTestRequestStep.class );
65 private HttpRequestConfig httpRequestConfig;
66 private HttpTestRequest testRequest;
67 private WsdlSubmit<HttpRequest> submit;
68
69 public HttpTestRequestStep( WsdlTestCase testCase, TestStepConfig config, boolean forLoadTest )
70 {
71 super( testCase, config, true, forLoadTest );
72
73 if( getConfig().getConfig() != null )
74 {
75
76
77 httpRequestConfig = RestRequestConverter.updateIfNeeded( getConfig().getConfig() );
78 if( httpRequestConfig != getConfig().getConfig() )
79 getConfig().setConfig( httpRequestConfig );
80 testRequest = buildTestRequest( forLoadTest );
81
82
83 testRequest.addPropertyChangeListener( this );
84 testRequest.addTestPropertyListener( new InternalTestPropertyListener() );
85
86 if( config.isSetName() )
87 testRequest.setName( config.getName() );
88 else
89 config.setName( testRequest.getName() );
90
91
92 }
93 else
94 {
95 httpRequestConfig = ( HttpRequestConfig )getConfig().addNewConfig().changeType( HttpRequestConfig.type );
96 }
97
98 for( TestProperty property : testRequest.getProperties().values() )
99 {
100 addProperty( new RestTestStepProperty( ( RestParamProperty )property ) );
101 }
102
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
109
110
111 addProperty( new TestStepBeanProperty( "Request", false, testRequest, "requestContent", this )
112 {
113 @Override
114 public String getDefaultValue()
115 {
116 return createDefaultRequestContent();
117 }
118 } );
119
120 addProperty( new TestStepBeanProperty( "ResponseAsXml", true, testRequest, "responseContentAsXml", this )
121 {
122 @Override
123 public String getDefaultValue()
124 {
125 return createDefaultResponseXmlContent();
126 }
127 } );
128
129 addProperty( new TestStepBeanProperty( "Response", true, testRequest, "responseContentAsString", this )
130 {
131 @Override
132 public String getDefaultValue()
133 {
134 return createDefaultRawResponseContent();
135 }
136 } );
137 }
138
139 protected HttpTestRequest buildTestRequest( boolean forLoadTest )
140 {
141 return new HttpTestRequest( httpRequestConfig, this, forLoadTest );
142 }
143
144 protected String createDefaultRawResponseContent()
145 {
146 return "";
147 }
148
149 protected String createDefaultResponseXmlContent()
150 {
151 return "";
152 }
153
154 protected String createDefaultRequestContent()
155 {
156 return "";
157 }
158
159 public HttpRequestConfig getRequestStepConfig()
160 {
161 return httpRequestConfig;
162 }
163
164 @Override
165 public WsdlTestStep clone( WsdlTestCase targetTestCase, String name )
166 {
167 beforeSave();
168
169 TestStepConfig config = ( TestStepConfig )getConfig().copy();
170 RequestStepConfig stepConfig = ( RequestStepConfig )config.getConfig().changeType( RequestStepConfig.type );
171
172 while( stepConfig.getRequest().sizeOfAttachmentArray() > 0 )
173 stepConfig.getRequest().removeAttachment( 0 );
174
175 config.setName( name );
176 stepConfig.getRequest().setName( name );
177
178 WsdlTestRequestStep result = ( WsdlTestRequestStep )targetTestCase.addTestStep( config );
179 testRequest.copyAttachmentsTo( result.getTestRequest() );
180
181 return result;
182 }
183
184 @Override
185 public void release()
186 {
187 super.release();
188
189
190 if( testRequest != null )
191 {
192 testRequest.removePropertyChangeListener( this );
193 testRequest.release();
194 }
195 }
196
197 @Override
198 public void resetConfigOnMove( TestStepConfig config )
199 {
200 super.resetConfigOnMove( config );
201
202 httpRequestConfig = ( HttpRequestConfig )config.getConfig().changeType( HttpRequestConfig.type );
203 testRequest.updateConfig( httpRequestConfig );
204 }
205
206 @Override
207 public ImageIcon getIcon()
208 {
209 return testRequest == null ? null : testRequest.getIcon();
210 }
211
212 public HttpTestRequest getTestRequest()
213 {
214 return testRequest;
215 }
216
217 @Override
218 public void setName( String name )
219 {
220 super.setName( name );
221 testRequest.setName( name );
222 }
223
224 public void propertyChange( PropertyChangeEvent evt )
225 {
226 if( evt.getPropertyName().equals( TestAssertion.CONFIGURATION_PROPERTY )
227 || evt.getPropertyName().equals( TestAssertion.DISABLED_PROPERTY ) )
228 {
229 if( getTestRequest().getResponse() != null )
230 {
231 getTestRequest().assertResponse( new WsdlTestRunContext( this ) );
232 }
233 }
234 else
235 {
236 if( evt.getSource() == testRequest && evt.getPropertyName().equals( WsdlTestRequest.NAME_PROPERTY ) )
237 {
238 if( !super.getName().equals( ( String )evt.getNewValue() ) )
239 super.setName( ( String )evt.getNewValue() );
240 }
241
242 notifyPropertyChanged( evt.getPropertyName(), evt.getOldValue(), evt.getNewValue() );
243 }
244 }
245
246 public TestStepResult run( TestCaseRunner runner, TestCaseRunContext runContext )
247 {
248 RestRequestStepResult testStepResult = new RestRequestStepResult( this );
249
250 try
251 {
252 submit = testRequest.submit( runContext, false );
253 HttpResponse response = ( HttpResponse )submit.getResponse();
254
255 if( submit.getStatus() != Submit.Status.CANCELED )
256 {
257 if( submit.getStatus() == Submit.Status.ERROR )
258 {
259 testStepResult.setStatus( TestStepStatus.FAILED );
260 testStepResult.addMessage( submit.getError().toString() );
261
262 testRequest.setResponse( null, runContext );
263 }
264 else if( response == null )
265 {
266 testStepResult.setStatus( TestStepStatus.FAILED );
267 testStepResult.addMessage( "Request is missing response" );
268
269 testRequest.setResponse( null, runContext );
270 }
271 else
272 {
273 runContext.setProperty( AssertedXPathsContainer.ASSERTEDXPATHSCONTAINER_PROPERTY, testStepResult );
274 testRequest.setResponse( response, runContext );
275
276 testStepResult.setTimeTaken( response.getTimeTaken() );
277 testStepResult.setSize( response.getContentLength() );
278 testStepResult.setResponse( response );
279
280 switch( testRequest.getAssertionStatus() )
281 {
282 case FAILED :
283 testStepResult.setStatus( TestStepStatus.FAILED );
284 break;
285 case VALID :
286 testStepResult.setStatus( TestStepStatus.OK );
287 break;
288 case UNKNOWN :
289 testStepResult.setStatus( TestStepStatus.UNKNOWN );
290 break;
291 }
292 }
293 }
294 else
295 {
296 testStepResult.setStatus( TestStepStatus.CANCELED );
297 testStepResult.addMessage( "Request was canceled" );
298 }
299
300 if( response != null )
301 {
302 testStepResult.setRequestContent( response.getRequestContent() );
303 testStepResult.addProperty( "URL", response.getURL() == null ? "<missing>" : response.getURL().toString() );
304 testStepResult.addProperty( "Method", String.valueOf( response.getMethod() ) );
305 testStepResult.addProperty( "StatusCode", String.valueOf( response.getStatusCode() ) );
306 testStepResult.addProperty( "HTTP Version", response.getHttpVersion() );
307 }
308 else
309 {
310 testStepResult.addMessage( "Missing Response" );
311 testStepResult.setRequestContent( testRequest.getRequestContent() );
312 }
313 }
314 catch( SubmitException e )
315 {
316 testStepResult.setStatus( TestStepStatus.FAILED );
317 testStepResult.addMessage( "SubmitException: " + e );
318 }
319 finally
320 {
321 submit = null;
322 }
323
324 testStepResult.setDomain( PropertyExpander.expandProperties( runContext, testRequest.getDomain() ) );
325 testStepResult.setUsername( PropertyExpander.expandProperties( runContext, testRequest.getUsername() ) );
326 testStepResult.setEndpoint( PropertyExpander.expandProperties( runContext, testRequest.getEndpoint() ) );
327 testStepResult.setPassword( PropertyExpander.expandProperties( runContext, testRequest.getPassword() ) );
328 testStepResult.setEncoding( PropertyExpander.expandProperties( runContext, testRequest.getEncoding() ) );
329
330 if( testStepResult.getStatus() != TestStepStatus.CANCELED )
331 {
332 AssertionStatus assertionStatus = testRequest.getAssertionStatus();
333 switch( assertionStatus )
334 {
335 case FAILED :
336 {
337 testStepResult.setStatus( TestStepStatus.FAILED );
338 if( getAssertionCount() == 0 )
339 {
340 testStepResult.addMessage( "Invalid/empty response" );
341 }
342 else
343 for( int c = 0; c < getAssertionCount(); c++ )
344 {
345 WsdlMessageAssertion assertion = getAssertionAt( c );
346 AssertionError[] errors = assertion.getErrors();
347 if( errors != null )
348 {
349 for( AssertionError error : errors )
350 {
351 testStepResult.addMessage( "[" + assertion.getName() + "] " + error.getMessage() );
352 }
353 }
354 }
355
356 break;
357 }
358 }
359 }
360
361 return testStepResult;
362 }
363
364 public WsdlMessageAssertion getAssertionAt( int index )
365 {
366 return testRequest.getAssertionAt( index );
367 }
368
369 public int getAssertionCount()
370 {
371 return testRequest == null ? 0 : testRequest.getAssertionCount();
372 }
373
374 @Override
375 public boolean cancel()
376 {
377 if( submit == null )
378 return false;
379
380 submit.cancel();
381
382 return true;
383 }
384
385 @Override
386 public boolean dependsOn( AbstractWsdlModelItem<?> modelItem )
387 {
388 return false;
389 }
390
391 @Override
392 public void beforeSave()
393 {
394 super.beforeSave();
395
396 if( testRequest != null )
397 testRequest.beforeSave();
398 }
399
400 @Override
401 public String getDescription()
402 {
403 return testRequest == null ? "<missing>" : testRequest.getDescription();
404 }
405
406 @Override
407 public void setDescription( String description )
408 {
409 if( testRequest != null )
410 testRequest.setDescription( description );
411 }
412
413 @SuppressWarnings("unchecked")
414 @Override
415 public List<? extends ModelItem> getChildren()
416 {
417 return testRequest == null ? Collections.EMPTY_LIST : testRequest.getAssertionList();
418 }
419
420 public PropertyExpansion[] getPropertyExpansions()
421 {
422 if( testRequest == null )
423 return new PropertyExpansion[0];
424
425 PropertyExpansionsResult result = new PropertyExpansionsResult( this, testRequest );
426
427 result.extractAndAddAll( "requestContent" );
428 result.extractAndAddAll( "endpoint" );
429 result.extractAndAddAll( "username" );
430 result.extractAndAddAll( "password" );
431 result.extractAndAddAll( "domain" );
432
433 StringToStringMap requestHeaders = testRequest.getRequestHeaders();
434 for( String key : requestHeaders.keySet() )
435 {
436 result.extractAndAddAll( new RequestHeaderHolder( requestHeaders, key ), "value" );
437 }
438
439 for( String key : testRequest.getParams().getPropertyNames() )
440 {
441 result.extractAndAddAll( new RequestParamHolder( key ), "value" );
442 }
443
444 return result.toArray( new PropertyExpansion[result.size()] );
445 }
446
447 public AbstractHttpRequest<?> getHttpRequest()
448 {
449 return testRequest;
450 }
451
452 public class RequestHeaderHolder
453 {
454 private final StringToStringMap valueMap;
455 private final String key;
456
457 public RequestHeaderHolder( StringToStringMap valueMap, String key )
458 {
459 this.valueMap = valueMap;
460 this.key = key;
461 }
462
463 public String getValue()
464 {
465 return valueMap.get( key );
466 }
467
468 public void setValue( String value )
469 {
470 valueMap.put( key, value );
471 testRequest.setRequestHeaders( valueMap );
472 }
473 }
474
475 public class RequestParamHolder
476 {
477 private final String name;
478
479 public RequestParamHolder( String name )
480 {
481 this.name = name;
482 }
483
484 public String getValue()
485 {
486 return testRequest.getParams().getPropertyValue( name );
487 }
488
489 public void setValue( String value )
490 {
491 testRequest.setPropertyValue( name, value );
492 }
493 }
494
495 public TestAssertion addAssertion( String type )
496 {
497 WsdlMessageAssertion result = testRequest.addAssertion( type );
498 return result;
499 }
500
501 public void addAssertionsListener( AssertionsListener listener )
502 {
503 testRequest.addAssertionsListener( listener );
504 }
505
506 public TestAssertion cloneAssertion( TestAssertion source, String name )
507 {
508 return testRequest.cloneAssertion( source, name );
509 }
510
511 public String getAssertableContent()
512 {
513 return testRequest.getAssertableContent();
514 }
515
516 public AssertableType getAssertableType()
517 {
518 return testRequest.getAssertableType();
519 }
520
521 public TestAssertion getAssertionByName( String name )
522 {
523 return testRequest.getAssertionByName( name );
524 }
525
526 public List<TestAssertion> getAssertionList()
527 {
528 return testRequest.getAssertionList();
529 }
530
531 public AssertionStatus getAssertionStatus()
532 {
533 return testRequest.getAssertionStatus();
534 }
535
536 public Interface getInterface()
537 {
538 return null;
539 }
540
541 public TestStep getTestStep()
542 {
543 return this;
544 }
545
546 public void removeAssertion( TestAssertion assertion )
547 {
548 testRequest.removeAssertion( assertion );
549 }
550
551 public void removeAssertionsListener( AssertionsListener listener )
552 {
553 testRequest.removeAssertionsListener( listener );
554 }
555
556 public TestAssertion moveAssertion( int ix, int offset )
557 {
558 return testRequest.moveAssertion( ix, offset );
559 }
560
561 public Map<String, TestAssertion> getAssertions()
562 {
563 return testRequest.getAssertions();
564 }
565
566 @Override
567 public void prepare( TestCaseRunner testRunner, TestCaseRunContext testRunContext ) throws Exception
568 {
569 super.prepare( testRunner, testRunContext );
570
571 testRequest.setResponse( null, testRunContext );
572
573 for( TestAssertion assertion : testRequest.getAssertionList() )
574 {
575 assertion.prepare( testRunner, testRunContext );
576 }
577 }
578
579 public String getDefaultSourcePropertyName()
580 {
581 return "ResponseAsXml";
582 }
583
584 public String getDefaultTargetPropertyName()
585 {
586 return "Request";
587 }
588
589 public String getDefaultAssertableContent()
590 {
591 return testRequest.getDefaultAssertableContent();
592 }
593
594 public void resolve( ResolveContext<?> context )
595 {
596 super.resolve( context );
597
598 testRequest.resolve( context );
599 }
600
601 private class InternalTestPropertyListener extends TestPropertyListenerAdapter
602 {
603 @Override
604 public void propertyAdded( String name )
605 {
606 HttpTestRequestStep.this.addProperty( new RestTestStepProperty( getTestRequest().getProperty( name ) ), true );
607 }
608
609 @Override
610 public void propertyRemoved( String name )
611 {
612 HttpTestRequestStep.this.deleteProperty( name, true );
613 }
614
615 @Override
616 public void propertyRenamed( String oldName, String newName )
617 {
618 HttpTestRequestStep.this.propertyRenamed( oldName );
619 }
620
621 @Override
622 public void propertyValueChanged( String name, String oldValue, String newValue )
623 {
624 HttpTestRequestStep.this.firePropertyValueChanged( name, oldValue, newValue );
625 }
626
627 @Override
628 public void propertyMoved( String name, int oldIndex, int newIndex )
629 {
630 HttpTestRequestStep.this.firePropertyMoved( name, oldIndex, newIndex );
631 }
632 }
633
634 private class RestTestStepProperty implements TestStepProperty
635 {
636 private RestParamProperty property;
637
638 public RestTestStepProperty( RestParamProperty property )
639 {
640 this.property = property;
641 }
642
643 public TestStep getTestStep()
644 {
645 return HttpTestRequestStep.this;
646 }
647
648 public String getName()
649 {
650 return property.getName();
651 }
652
653 public String getDescription()
654 {
655 return property.getDescription();
656 }
657
658 public String getValue()
659 {
660 return property.getValue();
661 }
662
663 public String getDefaultValue()
664 {
665 return property.getDefaultValue();
666 }
667
668 public void setValue( String value )
669 {
670 property.setValue( value );
671 }
672
673 public boolean isReadOnly()
674 {
675 return false;
676 }
677
678 public QName getType()
679 {
680 return property.getType();
681 }
682
683 public ModelItem getModelItem()
684 {
685 return getTestRequest();
686 }
687 }
688
689 }