1 17 18 package org.apache.jmeter.assertions; 19 20 import java.io.ByteArrayInputStream ; 21 import java.io.IOException ; 22 import java.io.Serializable ; 23 24 import javax.xml.parsers.ParserConfigurationException ; 25 import javax.xml.transform.TransformerException ; 26 27 import junit.framework.TestCase; 28 import junit.textui.TestRunner; 29 30 import org.apache.jmeter.samplers.SampleResult; 31 import org.apache.jmeter.testelement.AbstractTestElement; 32 import org.apache.jmeter.testelement.property.BooleanProperty; 33 import org.apache.jmeter.testelement.property.StringProperty; 34 import org.apache.jmeter.threads.JMeterContext; 35 import org.apache.jmeter.threads.JMeterContextService; 36 import org.apache.jmeter.threads.JMeterVariables; 37 import org.apache.jmeter.util.XPathUtil; 38 import org.apache.jorphan.logging.LoggingManager; 39 import org.apache.log.Logger; 40 import org.apache.xpath.XPathAPI; 41 import org.w3c.dom.Document ; 42 import org.w3c.dom.NodeList ; 43 import org.xml.sax.SAXException ; 44 45 46 47 52 public class XPathAssertion extends AbstractTestElement implements 53 Serializable , Assertion { 54 private static final Logger log = LoggingManager.getLoggerForClass(); 55 56 57 private static XPathAPI xpath = null; 58 59 private static final String XPATH_KEY = "XPath.xpath"; 60 private static final String WHITESPACE_KEY = "XPath.whitespace"; 61 private static final String VALIDATE_KEY = "XPath.validate"; 62 private static final String TOLERANT_KEY = "XPath.tolerant"; 63 private static final String NEGATE_KEY = "XPath.negate"; 64 private static final String NAMESPACE_KEY = "XPath.namespace"; 65 66 public static final String DEFAULT_XPATH = "/"; 67 68 69 70 75 public AssertionResult getResult(SampleResult response) { 76 AssertionResult result = new AssertionResult(); 78 if (response.getResponseData() == null) { 79 return setResultForNull(result); 80 } 81 result.setFailure(false); 82 result.setFailureMessage(""); 83 84 if (log.isDebugEnabled()){ 85 log.debug(new StringBuffer ("Validation is set to ").append(isValidating()).toString()); 86 log.debug(new StringBuffer ("Whitespace is set to ").append(isWhitespace()).toString()); 87 log.debug(new StringBuffer ("Tolerant is set to ").append(isTolerant()).toString()); 88 } 89 90 Document doc = null; 91 92 try { 93 doc = XPathUtil.makeDocument( 94 new ByteArrayInputStream (response.getResponseData()), 95 isValidating(), isWhitespace(), isNamespace(), isTolerant()); 96 }catch (SAXException e) { 97 log.debug("Caught sax exception: "+e); 98 result.setError(true); 99 result.setFailureMessage(new StringBuffer ("SAXException: ").append(e.getMessage()).toString()); 100 return result; 101 } catch (IOException e) { 102 log.warn("Cannot parse result content", e); 103 result.setError(true); 104 result.setFailureMessage(new StringBuffer ("IOException: ").append(e.getMessage()).toString()); 105 return result; 106 } catch (ParserConfigurationException e) { 107 log.warn("Cannot parse result content", e); 108 result.setError(true); 109 result.setFailureMessage(new StringBuffer ("ParserConfigurationException: ").append(e.getMessage()).toString()); 110 return result; 111 } 112 113 if ( doc == null || doc.getDocumentElement() == null){ 114 result.setError(true); 115 result.setFailureMessage("Document is null, probably not parsable"); 116 return result; 117 } 118 119 NodeList nodeList = null; 120 121 try { 122 nodeList = XPathAPI.selectNodeList(doc, getXPathString()); 123 } catch (TransformerException e) { 124 result.setError(true); 125 result.setFailureMessage(new StringBuffer ("TransformerException: ").append(e.getMessage()).toString()); 126 return result; 127 } 128 129 if ( nodeList == null || nodeList.getLength() == 0 ) { 130 log.debug(new StringBuffer ("nodeList null no match ").append(getXPathString()).toString()); 131 result.setFailure(!isNegated()); 132 result.setFailureMessage("No Nodes Matched " + getXPathString()); 133 return result; 134 } 135 log.debug("nodeList length "+nodeList.getLength()); 136 if (log.isDebugEnabled() &! isNegated()){ 137 for (int i=0; i< nodeList.getLength(); i++) 138 log.debug(new StringBuffer ("nodeList[").append(i).append("] ").append(nodeList.item(i)).toString()); 139 } 140 result.setFailure(isNegated()); 141 if (isNegated()) 142 result.setFailureMessage("Specified XPath was found... Turn off negate if this is not desired"); 143 return result; 144 } 145 146 private AssertionResult setResultForNull(AssertionResult result) { 147 result.setError(false); 148 result.setFailure(true); 149 result.setFailureMessage("Response was null"); 150 return result; 151 } 152 153 158 public String getXPathString() { 159 return getPropertyAsString(XPATH_KEY, DEFAULT_XPATH); 160 } 161 162 168 private String getPropertyAsString(String key, String defaultValue){ 169 String str = getPropertyAsString(key); 170 return (str == null || str.length() == 0) ? defaultValue : str; 171 } 172 173 177 public void setXPathString(String xpath) { 178 setProperty(new StringProperty(XPATH_KEY, xpath)); 179 } 180 181 185 public void setWhitespace(boolean whitespace) { 186 setProperty(new BooleanProperty(WHITESPACE_KEY, whitespace)); 187 } 188 189 193 public void setValidating(boolean validate) { 194 setProperty(new BooleanProperty(VALIDATE_KEY, validate)); 195 } 196 197 201 public void setNamespace(boolean namespace) { 202 setProperty(new BooleanProperty(NAMESPACE_KEY, namespace)); 203 } 204 205 209 public void setTolerant(boolean tolerant) { 210 setProperty(new BooleanProperty(TOLERANT_KEY, tolerant)); 211 } 212 213 public void setNegated(boolean negate){ 214 setProperty(new BooleanProperty(NEGATE_KEY, negate)); 215 } 216 217 221 public boolean isWhitespace() { 222 return getPropertyAsBoolean(WHITESPACE_KEY, false); 223 } 224 225 229 public boolean isValidating() { 230 return getPropertyAsBoolean(VALIDATE_KEY, false); 231 } 232 236 public boolean isNamespace() { 237 return getPropertyAsBoolean( NAMESPACE_KEY, false); 238 } 239 240 244 public boolean isTolerant() { 245 return getPropertyAsBoolean(TOLERANT_KEY, false); 246 } 247 248 253 public boolean isNegated() { 254 return getPropertyAsBoolean(NEGATE_KEY, false); 255 } 256 257 259 public static class XPathAssertionTest extends TestCase { 260 261 XPathAssertion assertion; 262 SampleResult result; 263 JMeterVariables vars; 264 JMeterContext jmctx; 265 public XPathAssertionTest() {super();} 266 public XPathAssertionTest(String name) 267 { 268 super(name); 269 } 270 public void setUp() { 271 jmctx = JMeterContextService.getContext(); 272 assertion = new XPathAssertion(); 273 assertion.setThreadContext(jmctx); 276 result = new SampleResult(); 277 String data = 278 "<company-xmlext-query-ret>" + 279 "<row>" + 280 "<value field=\"RetCode\">LIS_OK</value>" + 281 "<value field=\"RetCodeExtension\"></value>" + 282 "<value field=\"alias\"></value>" + 283 "<value field=\"positioncount\"></value>" + 284 "<value field=\"invalidpincount\">0</value>" + 285 "<value field=\"pinposition1\">1</value>" + 286 "<value field=\"pinpositionvalue1\"></value>" + 287 "<value field=\"pinposition2\">5</value>" + 288 "<value field=\"pinpositionvalue2\"></value>" + 289 "<value field=\"pinposition3\">6</value>" + 290 "<value field=\"pinpositionvalue3\"></value>" + 291 "</row>" + 292 "</company-xmlext-query-ret>"; 293 result.setResponseData(data.getBytes()); 294 vars = new JMeterVariables(); 295 jmctx.setVariables(vars); 296 jmctx.setPreviousResult(result); 297 } 298 299 public void testAssertion() throws Exception { 300 assertion.setXPathString("//row/value[@field = 'alias']"); 301 AssertionResult res = assertion.getResult(jmctx.getPreviousResult()); 302 log.debug(" res "+res.isError()); 303 log.debug(" failure "+res.getFailureMessage()); 304 assertFalse(res.isError()); 305 assertFalse(res.isFailure()); 306 } 307 public void testNegateAssertion() throws Exception { 308 assertion.setXPathString("//row/value[@field = 'noalias']"); 309 assertion.setNegated(true); 310 311 AssertionResult res = assertion.getResult(jmctx.getPreviousResult()); 312 log.debug(" res "+res.isError()); 313 log.debug(" failure "+res.getFailureMessage()); 314 assertFalse(res.isError()); 315 assertFalse(res.isFailure()); 316 } 317 public void testValidationFailure() throws Exception { 318 assertion.setXPathString("//row/value[@field = 'alias']"); 319 assertion.setNegated(false); 320 assertion.setValidating(true); 321 AssertionResult res = assertion.getResult(jmctx.getPreviousResult()); 322 log.debug(res.getFailureMessage()+" error: "+res.isError()+" failure: "+res.isFailure()); 323 assertTrue(res.isError()); 324 assertFalse(res.isFailure()); 325 326 } 327 public void testValidationSuccess() throws Exception { 328 String data ="<?xml version=\"1.0\"?>" 329 +"<!DOCTYPE BOOK [" 330 +"<!ELEMENT p (#PCDATA)>" 331 +"<!ELEMENT BOOK (OPENER,SUBTITLE?,INTRODUCTION?,(SECTION | PART)+)>" 332 +"<!ELEMENT OPENER (TITLE_TEXT)*>" 333 +"<!ELEMENT TITLE_TEXT (#PCDATA)>" 334 +"<!ELEMENT SUBTITLE (#PCDATA)>" 335 +"<!ELEMENT INTRODUCTION (HEADER, p+)+>" 336 +"<!ELEMENT PART (HEADER, CHAPTER+)>" 337 +"<!ELEMENT SECTION (HEADER, p+)>" 338 +"<!ELEMENT HEADER (#PCDATA)>" 339 +"<!ELEMENT CHAPTER (CHAPTER_NUMBER, CHAPTER_TEXT)>" 340 +"<!ELEMENT CHAPTER_NUMBER (#PCDATA)>" 341 +"<!ELEMENT CHAPTER_TEXT (p)+>" 342 +"]>" 343 +"<BOOK>" 344 +"<OPENER>" 345 +"<TITLE_TEXT>All About Me</TITLE_TEXT>" 346 +"</OPENER>" 347 +"<PART>" 348 +"<HEADER>Welcome To My Book</HEADER>" 349 +"<CHAPTER>" 350 +"<CHAPTER_NUMBER>CHAPTER 1</CHAPTER_NUMBER>" 351 +"<CHAPTER_TEXT>" 352 +"<p>Glad you want to hear about me.</p>" 353 +"<p>There's so much to say!</p>" 354 +"<p>Where should we start?</p>" 355 +"<p>How about more about me?</p>" 356 +"</CHAPTER_TEXT>" 357 +"</CHAPTER>" 358 +"</PART>" 359 +"</BOOK>"; 360 361 result.setResponseData(data.getBytes()); 362 vars = new JMeterVariables(); 363 jmctx.setVariables(vars); 364 jmctx.setPreviousResult(result); 365 assertion.setXPathString("/"); 366 assertion.setValidating(true); 367 AssertionResult res = assertion.getResult(result); 368 assertFalse(res.isError()); 369 assertFalse(res.isFailure()); 370 } 371 public void testValidationFailureWithDTD() throws Exception { 372 String data ="<?xml version=\"1.0\"?>" 373 +"<!DOCTYPE BOOK [" 374 +"<!ELEMENT p (#PCDATA)>" 375 +"<!ELEMENT BOOK (OPENER,SUBTITLE?,INTRODUCTION?,(SECTION | PART)+)>" 376 +"<!ELEMENT OPENER (TITLE_TEXT)*>" 377 +"<!ELEMENT TITLE_TEXT (#PCDATA)>" 378 +"<!ELEMENT SUBTITLE (#PCDATA)>" 379 +"<!ELEMENT INTRODUCTION (HEADER, p+)+>" 380 +"<!ELEMENT PART (HEADER, CHAPTER+)>" 381 +"<!ELEMENT SECTION (HEADER, p+)>" 382 +"<!ELEMENT HEADER (#PCDATA)>" 383 +"<!ELEMENT CHAPTER (CHAPTER_NUMBER, CHAPTER_TEXT)>" 384 +"<!ELEMENT CHAPTER_NUMBER (#PCDATA)>" 385 +"<!ELEMENT CHAPTER_TEXT (p)+>" 386 +"]>" 387 +"<BOOK>" 388 +"<OPENER>" 389 +"<TITLE_TEXT>All About Me</TITLE_TEXT>" 390 +"</OPENER>" 391 +"<PART>" 392 +"<HEADER>Welcome To My Book</HEADER>" 393 +"<CHAPTER>" 394 +"<CHAPTER_NUMBER>CHAPTER 1</CHAPTER_NUMBER>" 395 +"<CHAPTER_TEXT>" 396 +"<p>Glad you want to hear about me.</p>" 397 +"<p>There's so much to say!</p>" 398 +"<p>Where should we start?</p>" 399 +"<p>How about more about me?</p>" 400 +"</CHAPTER_TEXT>" 401 +"</CHAPTER>" 402 +"<illegal>not defined in dtd</illegal>" 403 +"</PART>" 404 +"</BOOK>"; 405 406 result.setResponseData(data.getBytes()); 407 vars = new JMeterVariables(); 408 jmctx.setVariables(vars); 409 jmctx.setPreviousResult(result); 410 assertion.setXPathString("/"); 411 assertion.setValidating(true); 412 AssertionResult res = assertion.getResult(result); 413 log.debug("failureMessage: "+res.getFailureMessage()); 414 assertTrue(res.isError()); 415 assertFalse(res.isFailure()); 416 } 417 public void testTolerance() throws Exception { 418 String data ="<html><head><title>testtitle</title></head>" 419 +"<body>" 420 +"<p><i><b>invalid tag nesting</i></b><hr>" 421 +"</body></html>"; 422 423 result.setResponseData(data.getBytes()); 424 vars = new JMeterVariables(); 425 jmctx.setVariables(vars); 426 jmctx.setPreviousResult(result); 427 assertion.setXPathString("/html/head/title"); 428 assertion.setValidating(true); 429 assertion.setTolerant(true); 430 AssertionResult res = assertion.getResult(result); 431 log.debug("failureMessage: "+res.getFailureMessage()); 432 assertFalse(res.isFailure()); 433 assertFalse(res.isError()); 434 } 435 436 public void testNoTolerance() throws Exception { 437 String data ="<html><head><title>testtitle</title></head>" 438 +"<body>" 439 +"<p><i><b>invalid tag nesting</i></b><hr>" 440 +"</body></html>"; 441 442 result.setResponseData(data.getBytes()); 443 vars = new JMeterVariables(); 444 jmctx.setVariables(vars); 445 jmctx.setPreviousResult(result); 446 assertion.setXPathString("/html/head/title"); 447 assertion.setValidating(false); 448 assertion.setTolerant(false); 449 AssertionResult res = assertion.getResult(result); 450 log.debug("failureMessage: "+res.getFailureMessage()); 451 assertTrue(res.isError()); 452 assertFalse(res.isFailure()); 453 } 454 455 public static void main(String [] args) { 456 TestRunner.run(XPathAssertionTest.class); 457 } 458 } 459 } | Popular Tags |