28a9f268ef62b75130503ec5ef5bc3ae07f15a15
[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 JSON output file."""
18
19 import json
20 import re
21 import sys, getopt
22
23 from robot.api import ExecutionResult, ResultVisitor
24
25
26 class ExecutionTestChecker(ResultVisitor):
27     """Iterates through test cases."""
28
29     def __init__(self, vDeviceVersion):
30         self.vDeviceVersion = vDeviceVersion
31         self.out = []
32
33     def visit_test(self, test):
34         """Overloaded function. Called when test is found to process data.
35
36         :param test: Test to process.
37         :type test: ExecutionTestChecker
38         """
39
40         test_id = test.longname
41         test_status = 'Failed'
42         framesize = ''
43         throughput = ''
44         throughput_units = ''
45         workers_per_nic = ''
46         workers = ''
47
48         if any("PERFTEST" in tag for tag in test.tags):
49             if test.status == 'PASS':
50                 test_status = 'Passed'
51                 if any("PERFTEST_LONG" in tag for tag in test.tags):
52                     throughput = test.message.split(' ')[1]
53                     throughput_units = test.message.split(' ')[2]
54                 elif any("PERFTEST_SHORT" in tag for tag in test.tags):
55                     for keyword in test.keywords:
56                         for assign in keyword.assign:
57                             if assign == '${rate}':
58                                 temp = re.findall(r"(\d*\.\d+|\d+)([A-Za-z]*)",
59                                                   keyword.args[0])
60                                 throughput = temp[0][0]
61                                 throughput_units = temp[0][1]
62
63                 for keyword in test.keywords:
64                     for assign in keyword.assign:
65                         if assign == '${framesize}':
66                             framesize = keyword.args[0]
67                     if 'worker threads' in keyword.name:
68                         workers = keyword.name.split('\'')[1]
69                         workers_per_nic = keyword.name.split('\'')[3]
70
71             self.out.append({'testCase': {
72                 'testId': test_id,
73                 'testStatus': test_status,
74                 'workerThreads': workers,
75                 'workerThreadsPerNic': workers_per_nic,
76                 'testTags': [tag for tag in test.tags],
77                 'l2FrameSize': {'value': framesize,
78                                 'units': 'Bytes'},
79                 'throughput': {'value': throughput,
80                                'units': throughput_units},
81                 'vDevice': {'version': self.vDeviceVersion}}})
82
83
84 def parse_tests(xml_file, vDeviceVersion):
85     """Parser result of robot output file and return.
86
87     :param xml_file: Output.xml from robot run.
88     :param vDeviceVersion: vDevice version.
89     :type xml_file: file
90     :type vDeviceVersion: str
91
92     :return: JSON formatted output.
93     :rtype: dict
94     """
95
96     result = ExecutionResult(xml_file)
97     checker = ExecutionTestChecker(vDeviceVersion)
98     result.visit(checker)
99
100     return checker.out
101
102
103 def print_help():
104     """Print help on stdout."""
105
106     print "args: [-h] -i <input_log_file> -o <output_json_file>" + \
107           " -v <vpp_version>"
108
109
110 def print_error(msg):
111     """Print error message on stderr.
112
113     :param msg: Error message to print.
114     :type msg: str
115     :return: nothing
116     """
117
118     sys.stderr.write(msg+'\n')
119
120
121 def main(argv):
122     """Main function."""
123
124     _log_file = None
125     _json_file = None
126     _vpp = None
127
128     try:
129         opts, _ = getopt.getopt(argv, "hi:o:v:", ["help"])
130     except getopt.GetoptError:
131         print_help()
132         sys.exit(1)
133
134     for opt, arg in opts:
135         if opt in ('-h', "--help"):
136             print_help()
137             sys.exit()
138         elif opt == '-i':
139             _log_file = arg
140         elif opt == '-o':
141             _json_file = arg
142         elif opt == '-v':
143             _vpp = arg
144
145     if _log_file is None or _json_file is None or _vpp is None:
146         print_help()
147         sys.exit(1)
148
149     try:
150         with open(_log_file, 'r') as input_file:
151             with open(_json_file, 'w') as output_file:
152                 out = parse_tests(input_file, _vpp)
153                 json.dump(out, fp=output_file, sort_keys=True,
154                           indent=4, separators=(',', ': '))
155     except IOError as ex_error:
156         print_error(str(ex_error))
157         sys.exit(1)
158
159
160 if __name__ == "__main__":
161     main(sys.argv[1:])