001: /*
002: * Conditions Of Use
003: *
004: * This software was developed by employees of the National Institute of
005: * Standards and Technology (NIST), and others.
006: * This software is has been contributed to the public domain.
007: * As a result, a formal license is not needed to use the software.
008: *
009: * This software is provided "AS IS."
010: * NIST MAKES NO WARRANTY OF ANY KIND, EXPRESS, IMPLIED
011: * OR STATUTORY, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTY OF
012: * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT
013: * AND DATA ACCURACY. NIST does not warrant or make any representations
014: * regarding the use of the software or the results thereof, including but
015: * not limited to the correctness, accuracy, reliability or usefulness of
016: * the software.
017: *
018: *
019: */
020: /*******************************************************************************
021: * Product of NIST/ITL Advanced Networking Technologies Division (ANTD). *
022: * Author: M. Ranganathan (mranga@nist.gov) *
023: *******************************************************************************/
024: /**
025: * Implements Parser torture tests.
026: *
027: *@author M. Ranganathan < mranga@nist.gov >
028: *
029: */package test.torture;
030:
031: import gov.nist.javax.sip.address.*;
032: import gov.nist.javax.sip.parser.*;
033: import gov.nist.javax.sip.header.*;
034: import gov.nist.javax.sip.message.*;
035: import java.io.*;
036: import java.util.Hashtable;
037: import java.util.Enumeration; // ifdef J2SDK1.4
038: import javax.xml.parsers.SAXParserFactory; // endif
039: import org.xml.sax.Attributes;
040: import org.xml.sax.EntityResolver;
041: import org.xml.sax.InputSource;
042: import org.xml.sax.XMLReader;
043: import org.xml.sax.SAXException;
044: import org.xml.sax.SAXParseException;
045: import org.xml.sax.helpers.DefaultHandler;
046: import java.text.ParseException;
047:
048: public class Torture extends DefaultHandler implements
049: ParseExceptionListener, TagNames, TokenValues,
050: ConfigurationSwitches {
051:
052: // variables that I read from the xml file header.
053: protected static boolean debug = true;
054:
055: protected static long startTime;
056:
057: protected static int counter = 0;
058:
059: protected String testMessage;
060:
061: protected String encodedMessage;
062:
063: protected String testDescription;
064:
065: protected boolean debugFlag;
066:
067: protected boolean abortOnFail;
068:
069: protected String failureReason;
070:
071: protected String statusMessage;
072:
073: protected String exceptionHeader;
074:
075: protected String exceptionMessage;
076:
077: protected String exceptionClassName;
078:
079: protected boolean failureFlag;
080:
081: protected boolean successFlag;
082:
083: protected boolean outputParsedStructures;
084:
085: protected static boolean outputResults;
086:
087: private PrintStream testLogWriter;
088:
089: private Hashtable exceptionTable;
090:
091: private StringMsgParser stringParser;
092:
093: // These track which context the parser is currently parsing.
094: private boolean messageContext;
095:
096: private boolean exceptionTextContext;
097:
098: private boolean sipHeaderContext;
099:
100: private boolean sipURLContext;
101:
102: private boolean testCaseContext;
103:
104: private boolean descriptionContext;
105:
106: private boolean expectExceptionContext;
107:
108: private boolean expectExtensionContext;
109:
110: private boolean exceptionMessageContext;
111:
112: private String testMessageType;
113:
114: private static final String XML_DOCTYPE_IDENTIFIER = "<?xml version='1.0' encoding='us-ascii'?>";
115:
116: class MyEntityResolver implements EntityResolver {
117:
118: public InputSource resolveEntity(String publicId,
119: String systemId) throws SAXException, IOException {
120:
121: return new InputSource(Torture.class
122: .getResourceAsStream("torture.dtd"));
123: }
124:
125: }
126:
127: class TestLogWriter extends PrintStream {
128: public void println(String stuff) {
129: if (outputResults)
130: super .println();
131: }
132:
133: public TestLogWriter(FileOutputStream fos) {
134: super (fos);
135: }
136:
137: }
138:
139: class ExpectedException {
140: protected boolean fired;
141:
142: protected String exceptionHeader;
143:
144: protected String exceptionMessage;
145:
146: protected Class exceptionClass;
147:
148: protected ExpectedException(String className,
149: String headerString) {
150: try {
151: exceptionClass = Class.forName(className);
152: exceptionHeader = headerString;
153: fired = false;
154: } catch (ClassNotFoundException ex) {
155: ex.printStackTrace();
156: System.err.println(ex.getMessage());
157: testLogWriter.close();
158: System.exit(0);
159: }
160: }
161: }
162:
163: private void setFailure() {
164: failureFlag = true;
165: }
166:
167: public void handleException(ParseException ex,
168: SIPMessage sipMessage, Class headerClass,
169: String headerText, String messageText)
170: throws ParseException {
171: String exceptionString = headerText;
172: if (debugFlag) {
173: System.out.println(exceptionString);
174: }
175:
176: if (exceptionTable == null) {
177: formatFailureDiagnostic(ex,
178: "unexpected exception (no exceptions expected)");
179: setFailure();
180: if (debugFlag)
181: throw ex;
182: } else {
183: ExpectedException e = (ExpectedException) exceptionTable
184: .get(headerText.trim());
185: if (e == null) {
186: // Check if there is an exception handler for
187: // wildcard match.
188: e = (ExpectedException) exceptionTable.get(messageText
189: .trim());
190: }
191: if (e == null) {
192: formatFailureDiagnostic(ex, "unexpected exception "
193: + ex.getMessage());
194: setFailure();
195: if (debugFlag)
196: throw ex;
197: } else if (!ex.getClass().equals(e.exceptionClass)) {
198: setFailure();
199: formatFailureDiagnostic(ex, " got " + ex.getClass()
200: + " expecting " + e.exceptionClass.getName());
201: if (debugFlag)
202: throw ex;
203: } else {
204: e.exceptionMessage = headerText;
205: e.fired = true;
206: successFlag = true;
207: }
208: }
209: }
210:
211: public void characters(char[] ch, int start, int length) {
212: String str = new String(ch, start, length);
213: if (str.trim() == "")
214: return;
215: if (messageContext) {
216: if (testMessage == null)
217: testMessage = str;
218: else
219: testMessage += str;
220: } else if (descriptionContext) {
221: if (testDescription == null)
222: testDescription = str;
223: else
224: testDescription += str;
225: } else if (exceptionTextContext) {
226: if (exceptionHeader == null)
227: exceptionHeader = str;
228: else
229: exceptionHeader += str;
230: } else if (sipHeaderContext) {
231: if (testMessage == null)
232: testMessage = str;
233: else
234: testMessage += str;
235: } else if (sipURLContext) {
236: if (testMessage == null)
237: testMessage = str;
238: else
239: testMessage += str;
240: } else if (exceptionMessageContext) {
241: if (exceptionMessage == null)
242: exceptionMessage = str;
243: else
244: exceptionMessage += str;
245: }
246: }
247:
248: public void startElement(String namespaceURI, String local,
249: String name, Attributes attrs) throws SAXException {
250: if (name.compareTo(TORTURE) == 0) {
251: outputParsedStructures = false;
252: outputResults = false;
253: failureFlag = false;
254: debugFlag = false;
255:
256: String outputParsedString = attrs
257: .getValue(OUTPUT_PARSED_STRUCTURE);
258: if (outputParsedString != null
259: && outputParsedString.toLowerCase().compareTo(TRUE) == 0) {
260: outputParsedStructures = true;
261: }
262: String debugString = attrs.getValue(DEBUG);
263: if (debugString != null
264: && debugString.toLowerCase().compareTo(TRUE) == 0) {
265: debugFlag = true;
266: }
267: String abortString = attrs.getValue(ABORT_ON_FAIL);
268: if (abortString != null && abortString.compareTo(TRUE) == 0) {
269: abortOnFail = true;
270: } else
271: abortOnFail = false;
272:
273: outputResults = false;
274: String outputResultsString = attrs.getValue(OUTPUT_RESULTS);
275: if (outputResultsString != null
276: && outputResultsString.compareTo(TRUE) == 0) {
277: outputResults = true;
278: } else
279: outputResults = false;
280:
281: if (outputResults) {
282:
283: String testlog = attrs.getValue(TESTLOG);
284: if (testlog != null) {
285: try {
286: if (outputResults)
287: testLogWriter = new TestLogWriter(
288: new FileOutputStream(testlog, true));
289: } catch (IOException ex) {
290: System.err.println("Cannot open " + testlog
291: + " for write");
292: System.exit(0);
293: }
294: } else {
295: testLogWriter = System.out;
296: }
297: }
298:
299: emitString(XML_DOCTYPE_IDENTIFIER);
300:
301: emitTag(TEST_OUTPUT);
302: startTime = System.currentTimeMillis();
303:
304: } else if (name.compareTo(TESTCASE) == 0) {
305: // Starting a new test
306: counter++;
307: failureReason = "";
308: statusMessage = "";
309: failureFlag = false;
310: successFlag = false;
311: messageContext = false;
312: testCaseContext = false;
313: messageContext = false;
314: descriptionContext = false;
315: expectExtensionContext = false;
316: sipHeaderContext = false;
317: sipURLContext = false;
318: testDescription = null;
319: testMessage = null;
320: encodedMessage = null;
321: exceptionMessage = null;
322: exceptionTable = new Hashtable();
323: } else if (name.compareTo(MESSAGE) == 0) {
324: testMessageType = MESSAGE;
325: messageContext = true;
326: } else if (name.compareTo(SIP_HEADER) == 0) {
327: testMessageType = SIP_HEADER;
328: sipHeaderContext = true;
329: } else if (name.compareTo(SIP_URL) == 0) {
330: testMessageType = SIP_URL;
331: sipURLContext = true;
332: } else if (name.compareTo(DESCRIPTION) == 0) {
333: descriptionContext = true;
334: } else if (name.compareTo(EXPECT_EXCEPTION) == 0) {
335: expectExceptionContext = true;
336: exceptionClassName = attrs.getValue(EXCEPTION_CLASS);
337: } else if (name.compareTo(EXCEPTION_MESSAGE) == 0) {
338: exceptionMessageContext = true;
339: } else if (name.compareTo(EXCEPTION_TEXT) == 0) {
340: exceptionTextContext = true;
341: } else
342: throw new SAXException("Unrecognized tag " + name);
343:
344: }
345:
346: public void error(SAXParseException e) throws SAXParseException {
347: throw e;
348: }
349:
350: public void ignorableWhitespace(char buf[], int offset, int len)
351: throws SAXException {
352: // Ignore it
353: }
354:
355: public void endElement(String namespaceURI, String local,
356: String name) throws SAXException {
357: if (name.compareTo(TESTCASE) == 0) {
358: testCaseContext = false;
359: stringParser = new StringMsgParser();
360: // stringParser.disableInputTracking();
361:
362: stringParser.setParseExceptionListener(this );
363: SIPMessage sipMessage = null;
364: SIPHeader sipHeader = null;
365: SipUri sipURL = null;
366: try {
367: if (testMessageType.equals(MESSAGE)) {
368: sipMessage = stringParser
369: .parseSIPMessage(testMessage);
370: encodedMessage = sipMessage.encode();
371: } else if (testMessageType.equals(SIP_HEADER)) {
372: sipHeader = stringParser
373: .parseSIPHeader(testMessage);
374: encodedMessage = sipHeader.encode();
375: } else if (testMessageType.equals(SIP_URL)) {
376: sipURL = stringParser.parseSIPUrl(testMessage
377: .trim());
378: encodedMessage = sipURL.encode();
379: } else
380: throw new SAXException("Torture: Internal error");
381: } catch (ParseException ex) {
382: ex.printStackTrace();
383: try {
384: handleException(ex, null, new SipUri().getClass(),
385: testMessage, null);
386: } catch (ParseException ex1) {
387: ex1.printStackTrace();
388: System.out.println("Unexpected excception!");
389: System.exit(0);
390: }
391: } catch (Exception ex) {
392: ex.printStackTrace();
393: System.out.println("Unexpected excception!");
394: System.exit(0);
395:
396: }
397: Enumeration e = exceptionTable.elements();
398: while (e.hasMoreElements()) {
399: ExpectedException ex = (ExpectedException) e
400: .nextElement();
401: if (!ex.fired) {
402: formatFailureDiagnostic(ex,
403: "Expected Exception not trapped ");
404: } else {
405: formatStatusMessage(ex,
406: "Expected exception generated ");
407: }
408: }
409:
410: emitBeginTag(TESTCASE);
411: if (!failureFlag) {
412: emitAttribute(STATUS, "PASSED");
413: } else {
414: emitAttribute(STATUS, "FAILED");
415: }
416: emitEndTag();
417: emitTaggedCData(DESCRIPTION, testDescription);
418: if (encodedMessage != null)
419: emitTaggedCData(MESSAGE, encodedMessage);
420: else
421: emitTaggedCData(MESSAGE, testMessage);
422: if (failureFlag) {
423: emitTaggedData(DIAGNOSTIC_MESSAGES, failureReason);
424: }
425: if (successFlag) {
426: emitTaggedData(DIAGNOSTIC_MESSAGES, statusMessage);
427: }
428: if (outputParsedStructures) {
429: if (sipMessage != null) {
430: emitTaggedCData(PARSED_OUTPUT, sipMessage
431: .toString());
432: } else if (sipHeader != null) {
433: emitTaggedCData(PARSED_OUTPUT, sipHeader.toString());
434: } else if (sipURL != null) {
435: emitTaggedCData(PARSED_OUTPUT, sipURL.toString());
436: }
437: }
438: emitEndTag(TESTCASE);
439: if (failureFlag && abortOnFail) {
440: if (testLogWriter != null)
441: testLogWriter.close();
442: System.out.println("Failed -- bailing out!");
443: System.exit(0);
444: }
445:
446: } else if (name.compareTo(DESCRIPTION) == 0) {
447: descriptionContext = false;
448: } else if (name.compareTo(MESSAGE) == 0) {
449: messageContext = false;
450: } else if (name.compareTo(EXCEPTION_TEXT) == 0) {
451: exceptionTextContext = false;
452: } else if (name.compareTo(EXPECT_EXCEPTION) == 0) {
453: expectExceptionContext = false;
454: ExpectedException ex = new ExpectedException(
455: exceptionClassName, exceptionHeader);
456: if (exceptionHeader != null) {
457: this .exceptionTable.put(exceptionHeader.trim(), ex);
458: } else {
459: this .exceptionTable.put(testMessage.trim(), ex);
460: }
461: exceptionHeader = null;
462: } else if (name.compareTo(EXCEPTION_MESSAGE) == 0) {
463: exceptionMessageContext = false;
464: exceptionMessage = null;
465: } else if (name.compareTo(SIP_HEADER) == 0) {
466: sipHeaderContext = false;
467: } else if (name.compareTo(SIP_URL) == 0) {
468: sipURLContext = false;
469: } else if (name.compareTo(TORTURE) == 0) {
470: emitEndTag(TEST_OUTPUT);
471: if (outputResults)
472: testLogWriter.close();
473: }
474:
475: }
476:
477: protected void emitBeginTag(String tagName) {
478: if (outputResults)
479: testLogWriter.println(LESS_THAN + tagName);
480: }
481:
482: protected void emitTag(String tagName) {
483: if (outputResults)
484: testLogWriter.println(LESS_THAN + tagName + GREATER_THAN);
485: }
486:
487: protected void emitTaggedData(String tag, String data) {
488: if (outputResults) {
489: emitTag(tag);
490: testLogWriter.println(data);
491: emitEndTag(tag);
492: }
493: }
494:
495: /* A stand alone tag */
496: protected void emitBeginEndTag(String tagName) {
497: if (outputResults) {
498: testLogWriter.println(LESS_THAN + tagName + SLASH
499: + GREATER_THAN);
500: }
501: }
502:
503: protected void emitEndTag() {
504: if (outputResults)
505: testLogWriter.println(GREATER_THAN);
506: }
507:
508: protected void emitEndTag(String tagName) {
509: if (outputResults)
510: testLogWriter.println(LESS_THAN + SLASH + tagName
511: + GREATER_THAN);
512: }
513:
514: protected void emitTaggedCData(String str) {
515: if (outputResults)
516: testLogWriter.println("<![CDATA[" + str + "]]>");
517:
518: }
519:
520: protected void emitTaggedCData(String tag, String str) {
521: if (outputResults) {
522: emitTag(tag);
523: testLogWriter.println("<![CDATA[" + str + "]]>");
524: emitEndTag(tag);
525: }
526:
527: }
528:
529: protected void emitString(String str) {
530: if (outputResults)
531: testLogWriter.println(str);
532: }
533:
534: protected void emitAttribute(String attrName, String attrval) {
535: if (outputResults)
536: testLogWriter.println(attrName + EQUALS + "\"" + attrval
537: + "\"");
538: }
539:
540: protected String emitStringAttribute(String attrName, String attrval) {
541: return attrName + EQUALS + "\"" + attrval + "\"" + "\n";
542: }
543:
544: protected String emitStringTag(String tag) {
545: return "<" + tag + ">" + "\n";
546: }
547:
548: protected String emitStringBeginTag(String tag) {
549: return "<" + tag + "\n";
550: }
551:
552: protected String emitStringEndTag() {
553: return ">" + "\n";
554: }
555:
556: protected String emitStringEndTag(String tag) {
557: return "</" + tag + ">\n";
558: }
559:
560: protected String emitStringCData(String msg) {
561: return "<![CDATA[" + msg + "]]>\n";
562: }
563:
564: protected String emitStringCData(String tag, String msg) {
565: return emitStringTag(tag) + emitStringCData(msg)
566: + emitStringEndTag(tag);
567: }
568:
569: protected void formatFailureDiagnostic(ParseException ex,
570: String message) {
571:
572: failureReason += emitStringBeginTag(DIAGNOSTIC);
573: failureReason += emitStringAttribute(REASON, message);
574: failureReason += emitStringEndTag();
575:
576: failureReason += emitStringAttribute(EXCEPTION_CLASS, ex
577: .getClass().getName());
578:
579: failureReason += emitStringCData(EXCEPTION_TEXT, ex
580: .getMessage());
581:
582: // DataOutputStream dos = new DataOutputStream(bos);
583: ByteArrayOutputStream bos = new ByteArrayOutputStream(4096);
584: ex.printStackTrace(new PrintStream(bos, true));
585: failureReason += emitStringCData(STACK_TRACE, bos.toString());
586: failureReason += emitStringCData(MESSAGE, ex.getMessage());
587: failureReason += emitStringEndTag(DIAGNOSTIC);
588: }
589:
590: protected void formatFailureDiagnostic(String hdr, String reason) {
591: failureReason += emitStringBeginTag(DIAGNOSTIC);
592: failureReason += emitStringAttribute(STATUS, "BAD");
593: failureReason += emitStringAttribute(REASON, reason);
594: failureReason += emitStringEndTag();
595: failureReason += emitStringCData(EXCEPTION_TEXT, hdr);
596: failureReason += emitStringEndTag(DIAGNOSTIC);
597: }
598:
599: protected void formatFailureDiagnostic(ExpectedException ex,
600: String reason) {
601: failureReason += emitStringBeginTag(DIAGNOSTIC);
602: failureReason += emitStringAttribute(STATUS, "BAD");
603: failureReason += emitStringAttribute(REASON, reason);
604: failureReason += emitStringAttribute(EXCEPTION_CLASS,
605: ex.exceptionClass.getName());
606: failureReason += emitStringEndTag();
607: failureReason += emitStringCData(EXCEPTION_TEXT,
608: ex.exceptionHeader);
609: failureReason += emitStringEndTag(DIAGNOSTIC);
610: }
611:
612: protected void formatStatusMessage(String hdr, String reason) {
613: statusMessage += emitStringBeginTag(DIAGNOSTIC);
614: statusMessage += emitStringAttribute(STATUS, "OK");
615: statusMessage += emitStringAttribute(REASON, reason);
616: statusMessage += emitStringEndTag();
617: statusMessage += emitStringCData(EXCEPTION_TEXT, hdr);
618: statusMessage += emitStringEndTag(DIAGNOSTIC);
619: }
620:
621: protected void formatStatusMessage(ExpectedException ex,
622: String reason) {
623: statusMessage += emitStringBeginTag(DIAGNOSTIC);
624: statusMessage += emitStringAttribute(STATUS, "OK");
625: statusMessage += emitStringAttribute(REASON, reason);
626: statusMessage += emitStringAttribute(EXCEPTION_CLASS,
627: ex.exceptionClass.getName());
628: statusMessage += emitStringEndTag();
629: statusMessage += emitStringCData(EXCEPTION_TEXT,
630: ex.exceptionHeader);
631: statusMessage += emitStringEndTag(DIAGNOSTIC);
632: }
633:
634: public Torture() {
635:
636: }
637:
638: public void doTests() throws Exception {
639: String fileName;
640: fileName = "torture.xml";
641:
642: /* The tests do not check for content length */
643: StringMsgParser.setComputeContentLengthFromMessage(true);
644:
645: try {
646: SAXParserFactory saxParserFactory = SAXParserFactory
647: .newInstance();
648: XMLReader saxParser = saxParserFactory.newSAXParser()
649: .getXMLReader();
650:
651: saxParser.setEntityResolver(new MyEntityResolver());
652: saxParser.setContentHandler(this );
653: saxParser.setFeature(
654: "http://xml.org/sax/features/validation", true);
655: saxParser.parse(new InputSource(Torture.class
656: .getResourceAsStream(fileName)));
657: System.out.println("Elapsed time = "
658: + (System.currentTimeMillis() - startTime)
659: / counter);
660:
661: } catch (Exception ex) {
662: ex.printStackTrace();
663: throw ex;
664: }
665:
666: }
667:
668: }
|