| 1 19 20 package org.netbeans.modules.junit.output; 21 22 import java.io.IOException ; 23 import java.io.Reader ; 24 import org.openide.ErrorManager; 25 import org.openide.util.NbBundle; 26 import org.openide.xml.XMLUtil; 27 import org.xml.sax.Attributes ; 28 import org.xml.sax.InputSource ; 29 import org.xml.sax.SAXException ; 30 import org.xml.sax.XMLReader ; 31 import org.xml.sax.helpers.DefaultHandler ; 32 33 38 final class XmlOutputParser extends DefaultHandler { 39 40 41 private static final int STATE_OUT_OF_SCOPE = 1; 42 43 private static final int STATE_TESTSUITE = 2; 44 45 private static final int STATE_PROPERTIES = 3; 46 47 private static final int STATE_PROPERTY = 4; 48 49 private static final int STATE_TESTCASE = 8; 50 51 private static final int STATE_FAILURE = 12; 52 53 private static final int STATE_ERROR = 13; 54 55 private static final int STATE_OUTPUT_STD = 16; 56 57 private static final int STATE_OUTPUT_ERR = 17; 58 59 60 private int state = STATE_OUT_OF_SCOPE; 61 62 int unknownElemNestLevel = 0; 63 64 65 private final XMLReader xmlReader; 66 67 private Report report; 68 69 private Report.Testcase testcase; 70 71 private Report.Trouble trouble; 72 73 private StringBuffer charactersBuf; 74 75 76 private final RegexpUtils regexp; 77 78 83 static Report parseXmlOutput(Reader reader) throws SAXException , 84 IOException { 85 XmlOutputParser parser = new XmlOutputParser(); 86 try { 87 parser.xmlReader.parse(new InputSource (reader)); 88 } catch (SAXException ex) { 89 String message = ex.getMessage(); 90 int severity = ErrorManager.INFORMATIONAL; 91 if ((message != null) 92 && ErrorManager.getDefault().isLoggable(severity)) { 93 ErrorManager.getDefault().log( 94 severity, 95 "Exception while parsing XML output from JUnit: " + message); 97 } 98 throw ex; 99 } catch (IOException ex) { 100 assert false; 101 } finally { 102 reader.close(); } 104 return parser.report; 105 } 106 107 108 private XmlOutputParser() throws SAXException { 109 xmlReader = XMLUtil.createXMLReader(); 110 xmlReader.setContentHandler(this); 111 112 regexp = RegexpUtils.getInstance(); 113 } 114 115 117 public void startElement(String uri, 118 String localName, 119 String qName, 120 Attributes attrs) throws SAXException { 121 switch (state) { 122 case STATE_PROPERTIES: 124 if (qName.equals("property")) { 125 state = STATE_PROPERTY; 126 } else { 127 startUnknownElem(); 128 } 129 break; case STATE_TESTSUITE: 132 if (qName.equals("testcase")) { 133 testcase = createTestcaseReport( 134 attrs.getValue("classname"), 135 attrs.getValue("name"), 136 attrs.getValue("time")); 137 state = STATE_TESTCASE; 138 } else if (qName.equals("system-out")) { 139 state = STATE_OUTPUT_STD; 140 } else if (qName.equals("system-err")) { 141 state = STATE_OUTPUT_ERR; 142 } else if (qName.equals("properties")) { 143 state = STATE_PROPERTIES; 144 } else { 145 startUnknownElem(); 146 } 147 break; case STATE_TESTCASE: 150 if (qName.equals("failure")) { 151 state = STATE_FAILURE; 152 } else if (qName.equals("error")) { 153 state = STATE_ERROR; 154 } else { 155 startUnknownElem(); 156 } 157 if (state >= 0) { assert testcase != null; 159 trouble = new Report.Trouble(state == STATE_ERROR); 160 } 161 break; case STATE_OUT_OF_SCOPE: 164 if (qName.equals("testsuite")) { 165 report = createReport(attrs.getValue("name"), 166 attrs.getValue("tests"), 167 attrs.getValue("failures"), 168 attrs.getValue("errors"), 169 attrs.getValue("time")); 170 state = STATE_TESTSUITE; 171 } else { 172 startUnknownElem(); 173 } 174 break; case STATE_PROPERTY: 177 case STATE_FAILURE: 178 case STATE_ERROR: 179 case STATE_OUTPUT_STD: 180 case STATE_OUTPUT_ERR: 181 startUnknownElem(); 182 break; default: 185 assert state < 0; 186 unknownElemNestLevel++; 187 break; } 189 } 190 191 193 public void endElement(String uri, 194 String localName, 195 String qName) throws SAXException { 196 switch (state) { 197 case STATE_PROPERTIES: 199 assert qName.equals("properties"); 200 state = STATE_TESTSUITE; 201 break; case STATE_TESTSUITE: 204 assert qName.equals("testsuite"); 205 state = STATE_OUT_OF_SCOPE; 206 break; case STATE_TESTCASE: 209 assert qName.equals("testcase"); 210 211 assert testcase != null; 212 report.reportTest(testcase); 213 testcase = null; 214 state = STATE_TESTSUITE; 215 break; case STATE_OUT_OF_SCOPE: 218 assert false; 219 break; case STATE_PROPERTY: 222 assert qName.equals("property"); 223 state = STATE_PROPERTIES; 224 break; case STATE_FAILURE: 227 case STATE_ERROR: 228 assert (state == STATE_FAILURE && qName.equals("failure")) 229 || (state == STATE_ERROR && qName.equals("error")); 230 231 assert testcase != null; 232 assert trouble != null; 233 if (charactersBuf != null) { 234 parseTroubleReport(charactersBuf.toString(), trouble); 235 charactersBuf = null; 236 } 237 testcase.trouble = trouble; 238 trouble = null; 239 state = STATE_TESTCASE; 240 break; case STATE_OUTPUT_STD: 243 case STATE_OUTPUT_ERR: 244 assert (state == STATE_OUTPUT_STD && qName.equals("system-out")) 245 || (state == STATE_OUTPUT_ERR && qName.equals("system-err")); 246 if (charactersBuf != null) { 247 String [] output = getOutput(charactersBuf.toString()); 248 if (state == STATE_OUTPUT_STD) { 249 report.outputStd = output; 250 } else { 251 report.outputErr = output; 252 } 253 charactersBuf = null; 254 } 255 state = STATE_TESTSUITE; 256 break; default: 259 assert state < 0; 260 if (--unknownElemNestLevel == 0) { 261 state = -state; 262 } 263 break; } 265 } 266 267 269 private void startUnknownElem() { 270 state = -state; 271 unknownElemNestLevel++; 272 } 273 274 276 private Report createReport(String suiteName, 277 String testsCountStr, 278 String failuresStr, 279 String errorsStr, 280 String timeStr) { 281 282 if (suiteName == null) { 283 suiteName = NbBundle.getMessage(XmlOutputParser.class, 284 "UNNKOWN_NAME"); } 286 287 288 final String [] numberStrings = new String [] { testsCountStr, 289 failuresStr, 290 errorsStr }; 291 final int[] numbers = new int[numberStrings.length]; 292 for (int i = 0; i < numberStrings.length; i++) { 293 boolean ok; 294 String numberStr = numberStrings[i]; 295 if (numberStr == null) { 296 ok = false; 297 } else { 298 try { 299 numbers[i] = Integer.parseInt(numberStrings[i]); 300 ok = (numbers[i] >= 0); 301 } catch (NumberFormatException ex) { 302 ok = false; 303 } 304 } 305 if (!ok) { 306 numbers[i] = -1; 307 } 308 } 309 310 311 int timeMillis = regexp.parseTimeMillisNoNFE(timeStr); 312 313 314 Report report = new Report(suiteName); 315 report.totalTests = numbers[0]; 316 report.failures = numbers[1]; 317 report.errors = numbers[2]; 318 report.elapsedTimeMillis = timeMillis; 319 320 return report; 321 } 322 323 325 private Report.Testcase createTestcaseReport(String className, 326 String name, 327 String timeStr) { 328 Report.Testcase testcase = new Report.Testcase(); 329 testcase.className = className; 330 testcase.name = name; 331 testcase.timeMillis = regexp.parseTimeMillisNoNFE(timeStr); 332 333 return testcase; 334 } 335 336 338 public void characters(char[] ch, 339 int start, 340 int length) throws SAXException { 341 switch (state) { 342 case STATE_FAILURE: 343 case STATE_ERROR: 344 case STATE_OUTPUT_STD: 345 case STATE_OUTPUT_ERR: 346 if (charactersBuf == null) { 347 charactersBuf = new StringBuffer (512); 348 } 349 charactersBuf.append(ch, start, length); 350 break; 351 } 352 } 353 354 356 private void parseTroubleReport(String report, Report.Trouble trouble) { 357 final String [] lines = report.split("[\\r\\n]+"); 359 TroubleParser troubleParser = new TroubleParser(trouble, regexp); 360 for (String line : lines) { 361 if (troubleParser.processMessage(line)) { 362 return; 363 } 364 } 365 troubleParser.finishProcessing(); 366 } 367 368 370 private String [] getOutput(String string) { 371 String [] lines = string.split("(?:\\r|\\r\\n|\\n)"); 373 376 if ((lines.length >= 1) && (lines[lines.length - 1].length() == 0)) { 377 String [] temp = lines; 378 lines = new String [lines.length - 1]; 379 if (lines.length > 0) { 380 System.arraycopy(temp, 0, lines, 0, lines.length); 381 } 382 } 383 return lines; 384 } 385 386 } 387 | Popular Tags |