CSIT-221 Robot parser update
[csit.git] / resources / tools / robot_output_parser.py
1 #!/usr/bin/python
2
3 # Copyright (c) 2016 Cisco and/or its affiliates.
4 # Licensed under the Apache License, Version 2.0 (the "License");
5 # you may not use this file except in compliance with the License.
6 # You may obtain a copy of the License at:
7 #
8 #     http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
15
16 """Script parses the data taken by robot framework (output.xml) and dumps
17 intereted values into XML output file."""
18
19 import argparse
20 import sys
21 import xml.etree.ElementTree as ET
22
23 from robot.api import ExecutionResult, ResultVisitor
24
25
26 class ExecutionChecker(ResultVisitor):
27     """Iterates through test cases."""
28
29     def __init__(self, args):
30         self.root = ET.Element('build',
31                                attrib={'vdevice': args.vdevice})
32
33     def visit_suite(self, suite):
34         """Implements traversing through the suite and its direct children.
35
36         :param suite: Suite to process.
37         :type suite: Suite
38         :return: Nothing.
39         """
40         if self.start_suite(suite) is not False:
41             suite.suites.visit(self)
42             suite.tests.visit(self)
43             self.end_suite(suite)
44
45     def start_suite(self, suite):
46         """Called when suite starts.
47
48         :param suite: Suite to process.
49         :type suite: Suite
50         :return: Nothing.
51         """
52         pass
53
54     def end_suite(self, suite):
55         """Called when suite ends.
56
57         :param suite: Suite to process.
58         :type suite: Suite
59         :return: Nothing.
60         """
61         pass
62
63     def visit_test(self, test):
64         """Implements traversing through the test.
65
66         :param test: Test to process.
67         :type test: Test
68         :return: Nothing.
69         """
70         if self.start_test(test) is not False:
71             self.end_test(test)
72
73     def start_test(self, test):
74         """Called when test starts.
75
76         :param test: Test to process.
77         :type test: Test
78         :return: Nothing.
79         """
80         if any("PERFTEST_LONG" in tag for tag in test.tags):
81             if test.status == 'PASS':
82                 tags = []
83                 for tag in test.tags:
84                     tags.append(tag)
85                 for keyword in test.keywords:
86                     for assign in keyword.assign:
87                         if assign == '${framesize}':
88                             framesize = keyword.args[0]
89                     if 'worker threads' in keyword.name:
90                         workers = keyword.name.split('\'')[1]
91                         workers_per_nic = keyword.name.split('\'')[3]
92
93                 test_elem = ET.SubElement(self.root,
94                     test.parent.name.replace(" ",""))
95                 test_elem.attrib['name'] = test.parent.name
96                 test_elem.attrib['workerthreads'] = workers
97                 test_elem.attrib['workerspernic'] = workers_per_nic
98                 test_elem.attrib['framesize'] = framesize
99                 test_elem.attrib['tags'] = ', '.join(tags)
100                 test_elem.text = test.message.split(' ')[1]
101
102     def end_test(self, test):
103         """Called when test ends.
104
105         :param test: Test to process.
106         :type test: Test
107         :return: Nothing.
108         """
109         pass
110
111
112 def parse_tests(args):
113     """Process data from robot output.xml file and return XML data.
114
115     :param args: Parsed arguments.
116     :type args: ArgumentParser
117
118     :return: XML formatted output.
119     :rtype: ElementTree
120     """
121
122     result = ExecutionResult(args.input)
123     checker = ExecutionChecker(args)
124     result.visit(checker)
125
126     return checker.root
127
128
129 def print_error(msg):
130     """Print error message on stderr.
131
132     :param msg: Error message to print.
133     :type msg: str
134     :return: nothing
135     """
136
137     sys.stderr.write(msg+'\n')
138
139
140 def parse_args():
141     """Parse arguments from cmd line.
142
143     :return: Parsed arguments.
144     :rtype ArgumentParser
145     """
146
147     parser = argparse.ArgumentParser()
148     parser.add_argument("-i", "--input", required=True,
149                         type=argparse.FileType('r'),
150                         help="Robot XML log file")
151     parser.add_argument("-o", "--output", required=True,
152                         type=argparse.FileType('w'),
153                         help="XML output file")
154     parser.add_argument("-v", "--vdevice", required=True,
155                         help="VPP version")
156
157     return parser.parse_args()
158
159
160 def main():
161     """Main function."""
162
163     args = parse_args()
164
165     root = parse_tests(args)
166     ET.ElementTree.write(ET.ElementTree(root), args.output)
167
168
169 if __name__ == "__main__":
170     sys.exit(main())