1# Copyright 2008-2015 Nokia Networks 2# Copyright 2016- Robot Framework Foundation 3# 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 16from robot.errors import DataError 17 18 19class XmlElementHandler(object): 20 21 def __init__(self, execution_result, root_handler=None): 22 self._stack = [(root_handler or RootHandler(), execution_result)] 23 24 def start(self, elem): 25 handler, result = self._stack[-1] 26 handler = handler.get_child_handler(elem) 27 result = handler.start(elem, result) 28 self._stack.append((handler, result)) 29 30 def end(self, elem): 31 handler, result = self._stack.pop() 32 handler.end(elem, result) 33 34 35class _Handler(object): 36 37 def __init__(self): 38 self._child_handlers = dict((c.tag, c) for c in self._children()) 39 40 def _children(self): 41 return [] 42 43 def get_child_handler(self, elem): 44 try: 45 return self._child_handlers[elem.tag] 46 except KeyError: 47 raise DataError("Incompatible XML element '%s'." % elem.tag) 48 49 def start(self, elem, result): 50 return result 51 52 def end(self, elem, result): 53 pass 54 55 def _timestamp(self, elem, attr_name): 56 timestamp = elem.get(attr_name) 57 return timestamp if timestamp != 'N/A' else None 58 59 60class RootHandler(_Handler): 61 62 def _children(self): 63 return [RobotHandler()] 64 65 66class RobotHandler(_Handler): 67 tag = 'robot' 68 69 def start(self, elem, result): 70 generator = elem.get('generator', 'unknown').split()[0].upper() 71 result.generated_by_robot = generator == 'ROBOT' 72 if result.rpa is None: 73 result.rpa = elem.get('rpa', 'false') == 'true' 74 return result 75 76 def _children(self): 77 return [RootSuiteHandler(), StatisticsHandler(), ErrorsHandler()] 78 79 80class SuiteHandler(_Handler): 81 tag = 'suite' 82 83 def start(self, elem, result): 84 return result.suites.create(name=elem.get('name', ''), 85 source=elem.get('source'), 86 rpa=result.rpa) 87 88 def _children(self): 89 return [DocHandler(), MetadataHandler(), SuiteStatusHandler(), 90 KeywordHandler(), TestCaseHandler(), self] 91 92 93class RootSuiteHandler(SuiteHandler): 94 95 def start(self, elem, result): 96 result.suite.name = elem.get('name', '') 97 result.suite.source = elem.get('source') 98 result.suite.rpa = result.rpa 99 return result.suite 100 101 def _children(self): 102 return SuiteHandler._children(self)[:-1] + [SuiteHandler()] 103 104 105class TestCaseHandler(_Handler): 106 tag = 'test' 107 108 def start(self, elem, result): 109 return result.tests.create(name=elem.get('name', '')) 110 111 def _children(self): 112 return [DocHandler(), TagsHandler(), TimeoutHandler(), 113 TestStatusHandler(), KeywordHandler()] 114 115 116class KeywordHandler(_Handler): 117 tag = 'kw' 118 119 def start(self, elem, result): 120 return result.keywords.create(kwname=elem.get('name', ''), 121 libname=elem.get('library', ''), 122 type=elem.get('type', 'kw')) 123 124 def _children(self): 125 return [DocHandler(), ArgumentsHandler(), AssignHandler(), 126 TagsHandler(), TimeoutHandler(), KeywordStatusHandler(), 127 MessageHandler(), self] 128 129 130class MessageHandler(_Handler): 131 tag = 'msg' 132 133 def end(self, elem, result): 134 result.messages.create(elem.text or '', 135 elem.get('level', 'INFO'), 136 elem.get('html', 'no') == 'yes', 137 self._timestamp(elem, 'timestamp')) 138 139 140class _StatusHandler(_Handler): 141 tag = 'status' 142 143 def _set_status(self, elem, result): 144 result.status = elem.get('status', 'FAIL') 145 146 def _set_message(self, elem, result): 147 result.message = elem.text or '' 148 149 def _set_times(self, elem, result): 150 result.starttime = self._timestamp(elem, 'starttime') 151 result.endtime = self._timestamp(elem, 'endtime') 152 153 154class KeywordStatusHandler(_StatusHandler): 155 156 def end(self, elem, result): 157 self._set_status(elem, result) 158 self._set_times(elem, result) 159 if result.type == result.TEARDOWN_TYPE: 160 self._set_message(elem, result) 161 162 163class SuiteStatusHandler(_StatusHandler): 164 165 def end(self, elem, result): 166 self._set_message(elem, result) 167 self._set_times(elem, result) 168 169 170class TestStatusHandler(_StatusHandler): 171 172 def end(self, elem, result): 173 self._set_status(elem, result) 174 self._set_message(elem, result) 175 self._set_times(elem, result) 176 177 178class DocHandler(_Handler): 179 tag = 'doc' 180 181 def end(self, elem, result): 182 result.doc = elem.text or '' 183 184 185class MetadataHandler(_Handler): 186 tag = 'metadata' 187 188 def _children(self): 189 return [MetadataItemHandler()] 190 191 192class MetadataItemHandler(_Handler): 193 tag = 'item' 194 195 def end(self, elem, result): 196 result.metadata[elem.get('name', '')] = elem.text or '' 197 198 199class TagsHandler(_Handler): 200 tag = 'tags' 201 202 def _children(self): 203 return [TagHandler()] 204 205 206class TagHandler(_Handler): 207 tag = 'tag' 208 209 def end(self, elem, result): 210 result.tags.add(elem.text or '') 211 212 213class TimeoutHandler(_Handler): 214 tag = 'timeout' 215 216 def end(self, elem, result): 217 result.timeout = elem.get('value') 218 219 220class AssignHandler(_Handler): 221 tag = 'assign' 222 223 def _children(self): 224 return [AssignVarHandler()] 225 226 227class AssignVarHandler(_Handler): 228 tag = 'var' 229 230 def end(self, elem, result): 231 result.assign += (elem.text or '',) 232 233 234class ArgumentsHandler(_Handler): 235 tag = 'arguments' 236 237 def _children(self): 238 return [ArgumentHandler()] 239 240 241class ArgumentHandler(_Handler): 242 tag = 'arg' 243 244 def end(self, elem, result): 245 result.args += (elem.text or '',) 246 247 248class ErrorsHandler(_Handler): 249 tag = 'errors' 250 251 def start(self, elem, result): 252 return result.errors 253 254 def _children(self): 255 return [MessageHandler()] 256 257 258class StatisticsHandler(_Handler): 259 tag = 'statistics' 260 261 def get_child_handler(self, elem): 262 return self 263