diff --git a/pom.xml b/pom.xml index fc57cd8..e2fc1f6 100755 --- a/pom.xml +++ b/pom.xml @@ -37,21 +37,21 @@ - 2.176.3 - 1.17 - 2.19 - 2.30 - 1.23 - 2.66 - 3.2 + 2.277.4 + 1.22 + 2.23 + 2.41 + 1.49 + 2.90 + 3.7 1.7.1 2.0 1.25 - 1.56 - 1.19.0 - 1.20 + 1.76 + 1.25.0 + 1.34 2.13 - 2.11.2 + 2.40 2.6 8 @@ -62,7 +62,17 @@ https://www.github.com/jenkinsci/robot-plugin robot-2.0.0 - + + + + io.jenkins.tools.bom + bom-2.222.x + 10 + import + pom + + + org.jenkins-ci.plugins @@ -99,13 +109,13 @@ org.jenkins-ci.plugins.workflow workflow-basic-steps - ${workflow-basic-steps.version} + test org.jenkins-ci.plugins.workflow workflow-durable-task-step - ${workflow-durable-task-step.version} + test @@ -123,7 +133,7 @@ org.jenkins-ci.plugins matrix-project - ${matrix-project.version} + org.jenkins-ci.plugins @@ -149,6 +159,95 @@ ${mailer.version} true + + + + org.apache.commons + commons-lang3 + 3.12.0 + + + org.jenkins-ci.plugins + jackson2-api + 2.12.3 + + + org.jenkins-ci.plugins + display-url-api + 2.3.5 + + + org.jenkins-ci.plugins + scm-api + 2.6.4 + + + org.jenkins-ci.plugins + variant + 1.4 + + + org.jenkins-ci.plugins + credentials + 2.3.17 + + + org.jenkins-ci + symbol-annotation + 1.22 + + + org.jenkins-ci.plugins + cloudbees-folder + 6.15 + + + io.jenkins.plugins + snakeyaml-api + 1.27.0 + + + org.slf4j + slf4j-api + 1.7.30 + + + org.slf4j + log4j-over-slf4j + 1.7.30 + + + org.slf4j + slf4j-jdk14 + 1.7.30 + test + + + org.slf4j + jcl-over-slf4j + 1.7.30 + + + org.ow2.asm + asm + 9.0 + + + org.ow2.asm + asm-tree + 9.0 + + + org.ow2.asm + asm-analysis + 9.0 + + + org.ow2.asm + asm-util + 9.0 + + diff --git a/src/main/java/hudson/plugins/robot/RobotParser.java b/src/main/java/hudson/plugins/robot/RobotParser.java index 21290a5..cb527ec 100644 --- a/src/main/java/hudson/plugins/robot/RobotParser.java +++ b/src/main/java/hudson/plugins/robot/RobotParser.java @@ -285,16 +285,24 @@ private RobotCaseResult processTest(XMLStreamReader reader, RobotSuiteResult res StringBuilder stackTrace = new StringBuilder(); //parse stacktrace - String xmlTag = ignoreUntilStarts(reader, "kw", "for", "if", "doc", "tags", "tag", "status"); - while (xmlTag.equals("kw") || xmlTag.equals("for") || xmlTag.equals("if")) { - if (xmlTag.equals("if")) { - stackTrace.append(processIf(reader, 0)); - } else if (xmlTag.equals("for")) { - stackTrace.append(processForLoop(reader, 0)); - } else { - stackTrace.append(processKeyword(reader, 0)); + String[] possible_elements = {"kw", "for", "if", "try", "while", "doc", "tags", "tag", "status"}; + String[] elements = {"kw", "for", "if", "try", "while"}; + String xmlTag = ignoreUntilStarts(reader, possible_elements); + while (isNameInElements(xmlTag, elements)) { + switch (xmlTag) { + case "if": + case "try": + stackTrace.append(processBranchable(reader, 0)); + break; + case "for": + case "while": + stackTrace.append(processLoop(reader, 0)); + break; + default: + stackTrace.append(processKeyword(reader, 0)); + break; } - xmlTag = ignoreUntilStarts(reader, "kw", "for", "if", "doc", "tags", "tag", "status"); + xmlTag = ignoreUntilStarts(reader, possible_elements); } caseResult.setStackTrace(stackTrace.toString().trim().replaceAll("\n+", "\n")); @@ -341,12 +349,16 @@ private RobotCaseResult processTest(XMLStreamReader reader, RobotSuiteResult res return caseResult; } - private String processForLoop(XMLStreamReader reader, int nestedCount) throws XMLStreamException { + private String processLoop(XMLStreamReader reader, int nestedCount) throws XMLStreamException { StringBuilder stackTrace = new StringBuilder(); String indentation = getSpacesPerNestedLevel(nestedCount); - stackTrace.append(indentation + "FOR " + reader.getAttributeValue(null, "flavor")); + String kind = reader.getLocalName(); + stackTrace.append(indentation + kind.toUpperCase()); + if (kind.equals("for")) { + stackTrace.append(" " + reader.getAttributeValue(null, "flavor")); + } while (reader.hasNext()) { - if (reader.isEndElement() && reader.getLocalName().equals("for")) { + if (reader.isEndElement() && reader.getLocalName().equals(kind)) { break; } if (reader.isStartElement() && reader.getLocalName().equals("iter")) { @@ -366,14 +378,25 @@ private String processIteration(XMLStreamReader reader, int nestedCount) throws } if (reader.isStartElement()) { String xmlTag = reader.getLocalName(); - if (xmlTag.equals("for")) { - stackTrace.append(processForLoop(reader, nestedCount)); - } - if (xmlTag.equals("kw")) { - stackTrace.append(processKeyword(reader, nestedCount)); - } - if (xmlTag.equals("if")) { - stackTrace.append(processIf(reader, nestedCount)); + switch (xmlTag) { + case "for": + case "while": + stackTrace.append(processLoop(reader, nestedCount)); + break; + case "kw": + stackTrace.append(processKeyword(reader, nestedCount)); + break; + case "if": + case "try": + stackTrace.append(processBranchable(reader, nestedCount)); + break; + case "return": + case "break": + case "continue": + stackTrace.append(processReturnBreakContinue(reader, nestedCount)); + break; + default: + break; } } reader.next(); @@ -382,11 +405,12 @@ private String processIteration(XMLStreamReader reader, int nestedCount) throws return stackTrace.toString(); } - private String processIf(XMLStreamReader reader, int nestedCount) throws XMLStreamException { + private String processBranchable(XMLStreamReader reader, int nestedCount) throws XMLStreamException { StringBuilder stackTrace = new StringBuilder(); String indentation = getSpacesPerNestedLevel(nestedCount); + String kind = reader.getLocalName(); while (reader.hasNext()) { - if (reader.isEndElement() && reader.getLocalName().equals("if")) { + if (reader.isEndElement() && reader.getLocalName().equals(kind)) { break; } if (reader.isStartElement() && reader.getLocalName().equals("branch")) { @@ -407,14 +431,25 @@ private String processBranch(XMLStreamReader reader, int nestedCount) throws XML } if (reader.isStartElement()) { String xmlTag = reader.getLocalName(); - if (xmlTag.equals("for")) { - stackTrace.append(processForLoop(reader, nestedCount)); - } - if (xmlTag.equals("kw")) { - stackTrace.append(processKeyword(reader, nestedCount)); - } - if (xmlTag.equals("if")) { - stackTrace.append(processIf(reader, nestedCount)); + switch (xmlTag) { + case "for": + case "while": + stackTrace.append(processLoop(reader, nestedCount)); + break; + case "kw": + stackTrace.append(processKeyword(reader, nestedCount)); + break; + case "if": + case "try": + stackTrace.append(processBranchable(reader, nestedCount)); + break; + case "return": + case "break": + case "continue": + stackTrace.append(processReturnBreakContinue(reader, nestedCount)); + break; + default: + break; } } reader.next(); @@ -440,13 +475,20 @@ private String processKeyword(XMLStreamReader reader, int nestedCount) throws XM stackTrace.append(processArgs(reader)); continue; // processArgs returns with us already in . We don't want to use reader.next() case "for": - stackTrace.append(processForLoop(reader, nestedCount+1)); + case "while": + stackTrace.append(processLoop(reader, nestedCount+1)); break; case "kw": stackTrace.append(processKeyword(reader, nestedCount+1)); break; case "if": - stackTrace.append(processIf(reader, nestedCount+1)); + case "try": + stackTrace.append(processBranchable(reader, nestedCount+1)); + break; + case "return": + case "break": + case "continue": + stackTrace.append(processReturnBreakContinue(reader, nestedCount+1)); break; default: break; @@ -500,6 +542,22 @@ private List processTags(XMLStreamReader reader) throws XMLStreamExcepti return tagList; } + private String processReturnBreakContinue(XMLStreamReader reader, int nestedCount) throws XMLStreamException { + StringBuilder stringBuilder = new StringBuilder(); + String kind = reader.getLocalName(); + stringBuilder.append(getSpacesPerNestedLevel(nestedCount)).append(kind.toUpperCase()); + while(reader.hasNext()) { + if (reader.isEndElement() && reader.getLocalName().equals(kind)) { + break; + } + if (reader.isStartElement() && reader.getLocalName().equals("kw")) { + stringBuilder.append(processKeyword(reader, nestedCount+1)); + } + reader.next(); + } + return stringBuilder.toString(); + } + private static void setCriticalityIfAvailable(XMLStreamReader reader, RobotCaseResult caseResult) { String criticality = reader.getAttributeValue(null, "critical"); if (criticality != null) { diff --git a/src/test/java/hudson/plugins/robot/RobotParserTest.java b/src/test/java/hudson/plugins/robot/RobotParserTest.java index 5c358ca..765c591 100644 --- a/src/test/java/hudson/plugins/robot/RobotParserTest.java +++ b/src/test/java/hudson/plugins/robot/RobotParserTest.java @@ -183,6 +183,16 @@ public void testRobot4If() { final String dir = "."; final String mask = "robot4_if_output.xml"; parse(dir, mask); + } + /** Robot Framework 5.0 introduced TRY-EXCEPT, WHILE, + * BREAK, and CONTINUE. The output file contains simple + * test cases which use new features. + */ + @Test + public void testRobot5TryExceptFinallyWhileContinue() { + final String dir = "robot5"; + final String mask = "basic_new_features_output.xml"; + parse(dir, mask); } } diff --git a/src/test/resources/hudson/plugins/robot/robot5/basic_new_features_output.xml b/src/test/resources/hudson/plugins/robot/robot5/basic_new_features_output.xml new file mode 100644 index 0000000..592117b --- /dev/null +++ b/src/test/resources/hudson/plugins/robot/robot5/basic_new_features_output.xml @@ -0,0 +1,438 @@ + + + + + + + +mikki +hiiri + +${arg1} +${arg2} +Fails if the given objects are unequal. +mikki != hiiri + + + + + + + + +Error caught +Logs the given message with the given level. +Error caught + + + + + + + + + + + + +mikki +mikki + +${arg1} +${arg2} +Fails if the given objects are unequal. + + + + + + + + +Fails the test with the given message and optionally alters its tags. + + + + + + +Some message +Logs the given message with the given level. +Some message + + + + + + + + + + +${x} +5 +Returns the given values which can then be assigned to a variables. +${x} = 5 + + + + + +${x} +Logs the given message with the given level. +5 + + + +${x} +${x}-1 +Evaluates the given expression in Python and returns the result. +${x} = 4 + + + + + + +${x} +Logs the given message with the given level. +4 + + + +${x} +${x}-1 +Evaluates the given expression in Python and returns the result. +${x} = 3 + + + + + + +${x} +Logs the given message with the given level. +3 + + + +${x} +${x}-1 +Evaluates the given expression in Python and returns the result. +${x} = 2 + + + + + + +${x} +Logs the given message with the given level. +2 + + + +${x} +${x}-1 +Evaluates the given expression in Python and returns the result. +${x} = 1 + + + + + + +${x} +Logs the given message with the given level. +1 + + + +${x} +${x}-1 +Evaluates the given expression in Python and returns the result. +${x} = 0 + + + + + + + + + + +${x} +5 +Returns the given values which can then be assigned to a variables. +${x} = 5 + + + + + +${x} +Logs the given message with the given level. +5 + + + +${x} +${x}-1 +Evaluates the given expression in Python and returns the result. +${x} = 4 + + + + + + + + + + + + + + + +${x} +Logs the given message with the given level. +4 + + + +${x} +${x}-1 +Evaluates the given expression in Python and returns the result. +${x} = 3 + + + + + + + + + + + + + + + +${x} +Logs the given message with the given level. +3 + + + +${x} +${x}-1 +Evaluates the given expression in Python and returns the result. +${x} = 2 + + + + + + + + + + + + + + + + + + + +${x} +5 +Returns the given values which can then be assigned to a variables. +${x} = 5 + + + +${y} +${x} + +${result} +${arg1}-1 +Evaluates the given expression in Python and returns the result. +${result} = 4 + + + +${result} + + + +This should not be executed +Fails the test with the given message and optionally alters its tags. + + +${y} = 4 + + + +${y} +Logs the given message with the given level. +4 + + + + + + +${x} +5 +Returns the given values which can then be assigned to a variables. +${x} = 5 + + + + + +${x} +${x}-1 +Evaluates the given expression in Python and returns the result. +${x} = 4 + + + + + + + + + + + + +${x} +Logs the given message with the given level. + + + + + + +${x} +${x}-1 +Evaluates the given expression in Python and returns the result. +${x} = 3 + + + + + + + + + + + + +${x} +Logs the given message with the given level. +3 + + + + + + +${x} +${x}-1 +Evaluates the given expression in Python and returns the result. +${x} = 2 + + + + + + + + + + + + +${x} +Logs the given message with the given level. + + + + + + +${x} +${x}-1 +Evaluates the given expression in Python and returns the result. +${x} = 1 + + + + + + + + + + + + +${x} +Logs the given message with the given level. +1 + + + + + + +${x} +${x}-1 +Evaluates the given expression in Python and returns the result. +${x} = 0 + + + + + + + + + + + + +${x} +Logs the given message with the given level. + + + + + + + + + + + + +All Tests + + + + +Test + + + + +