X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=resources%2Ftools%2Frobot_output_parser.py;h=b9ad8f8aa9912f39124a42815e458cf6b861db99;hb=1fcfc9bcc91c9bf9f1ab10fab898efc0d8c1e25f;hp=ad1fbfae2a17ddb674344cb83c132b3a08368e2e;hpb=62ba63249e5d5e07c773303855a3a2a852ab459b;p=csit.git diff --git a/resources/tools/robot_output_parser.py b/resources/tools/robot_output_parser.py index ad1fbfae2a..b9ad8f8aa9 100755 --- a/resources/tools/robot_output_parser.py +++ b/resources/tools/robot_output_parser.py @@ -14,54 +14,136 @@ # limitations under the License. """Script parses the data taken by robot framework (output.xml) and dumps -intereted values into XML output file.""" +interested values into XML output file.""" import argparse +import re import sys import xml.etree.ElementTree as ET from robot.api import ExecutionResult, ResultVisitor -class ExecutionTestChecker(ResultVisitor): +class ExecutionChecker(ResultVisitor): """Iterates through test cases.""" + tc_regexp = re.compile(ur'^tc\d+-((\d+)B|IMIX)-(\d)t(\d)c-(.*)') + rate_regexp = re.compile(ur'^[\D\d]*FINAL_RATE:\s(\d+\.\d+)[\D\d]*') + lat_regexp = re.compile(ur'^[\D\d]*'\ + ur'LAT_\d+%NDR:\s\[\'(-?\d+\/-?\d+\/-?\d+)\','\ + ur'\s\'(-?\d+\/-?\d+\/-?\d+)\'\]\s\n'\ + ur'LAT_\d+%NDR:\s\[\'(-?\d+\/-?\d+\/-?\d+)\','\ + ur'\s\'(-?\d+\/-?\d+\/-?\d+)\'\]\s\n'\ + ur'LAT_\d+%NDR:\s\[\'(-?\d+\/-?\d+\/-?\d+)\','\ + ur'\s\'(-?\d+\/-?\d+\/-?\d+)\'\]') + def __init__(self, args): self.root = ET.Element('build', attrib={'vdevice': args.vdevice}) + def visit_suite(self, suite): + """Implements traversing through the suite and its direct children. + + :param suite: Suite to process. + :type suite: Suite + :return: Nothing. + """ + if self.start_suite(suite) is not False: + suite.suites.visit(self) + suite.tests.visit(self) + self.end_suite(suite) + + def start_suite(self, suite): + """Called when suite starts. + + :param suite: Suite to process. + :type suite: Suite + :return: Nothing. + """ + pass + + def end_suite(self, suite): + """Called when suite ends. + + :param suite: Suite to process. + :type suite: Suite + :return: Nothing. + """ + pass + def visit_test(self, test): - """Overloaded function. Called when test is found to process data. + """Implements traversing through the test. :param test: Test to process. - :type test: ExecutionTestChecker + :type test: Test + :return: Nothing. """ + if self.start_test(test) is not False: + self.end_test(test) + + def start_test(self, test): + """Called when test starts. - if any("PERFTEST_LONG" in tag for tag in test.tags): + :param test: Test to process. + :type test: Test + :return: Nothing. + """ + if any("NDRPDRDISC" in tag for tag in test.tags): if test.status == 'PASS': tags = [] for tag in test.tags: tags.append(tag) - for keyword in test.keywords: - for assign in keyword.assign: - if assign == '${framesize}': - framesize = keyword.args[0] - if 'worker threads' in keyword.name: - workers = keyword.name.split('\'')[1] - workers_per_nic = keyword.name.split('\'')[3] - - test_elem = ET.SubElement(self.root, - test.longname.split('.')[3].replace(" ","")) - test_elem.attrib['name'] = test.longname.split('.')[3] - test_elem.attrib['workerthreads'] = workers - test_elem.attrib['workerspernic'] = workers_per_nic - test_elem.attrib['framesize'] = framesize + + test_elem = ET.SubElement( + self.root, "S" + test.parent.name.replace(" ", "")) + test_elem.attrib['name'] = test.parent.name + test_elem.attrib['framesize'] = str(re.search( + self.tc_regexp, test.name).group(1)) + test_elem.attrib['threads'] = str(re.search( + self.tc_regexp, test.name).group(3)) + test_elem.attrib['cores'] = str(re.search( + self.tc_regexp, test.name).group(4)) + if any("NDRDISC" in tag for tag in test.tags): + try: + test_elem.attrib['lat_100'] = str(re.search( + self.lat_regexp, test.message).group(1)) + '/' +\ + str(re.search(self.lat_regexp, test.message). + group(2)) + except AttributeError: + test_elem.attrib['lat_100'] = "-1/-1/-1/-1/-1/-1" + try: + test_elem.attrib['lat_50'] = str(re.search( + self.lat_regexp, test.message).group(3)) + '/' +\ + str(re.search(self.lat_regexp, test.message). + group(4)) + except AttributeError: + test_elem.attrib['lat_50'] = "-1/-1/-1/-1/-1/-1" + try: + test_elem.attrib['lat_10'] = str(re.search( + self.lat_regexp, test.message).group(5)) + '/' +\ + str(re.search(self.lat_regexp, test.message). + group(6)) + except AttributeError: + test_elem.attrib['lat_10'] = "-1/-1/-1/-1/-1/-1" test_elem.attrib['tags'] = ', '.join(tags) - test_elem.text = test.message.split(' ')[1] + try: + test_elem.text = str(re.search( + self.rate_regexp, test.message).group(1)) + except AttributeError: + test_elem.text = "-1" + + def end_test(self, test): + """Called when test ends. + + :param test: Test to process. + :type test: Test + :return: Nothing. + """ + pass def parse_tests(args): - """Parser result of robot output file and return. + """Process data from robot output.xml file and return XML data. :param args: Parsed arguments. :type args: ArgumentParser @@ -71,7 +153,7 @@ def parse_tests(args): """ result = ExecutionResult(args.input) - checker = ExecutionTestChecker(args) + checker = ExecutionChecker(args) result.visit(checker) return checker.root @@ -85,7 +167,7 @@ def print_error(msg): :return: nothing """ - sys.stderr.write(msg+'\n') + sys.stderr.write(msg + '\n') def parse_args(): @@ -96,13 +178,18 @@ def parse_args(): """ parser = argparse.ArgumentParser() - parser.add_argument("-i", "--input", required=True, + parser.add_argument("-i", "--input", + required=True, type=argparse.FileType('r'), help="Robot XML log file") - parser.add_argument("-o", "--output", required=True, + parser.add_argument("-o", "--output", + required=True, type=argparse.FileType('w'), help="XML output file") - parser.add_argument("-v", "--vdevice", required=True, + parser.add_argument("-v", "--vdevice", + required=False, + default="", + type=str, help="VPP version") return parser.parse_args()