#!/usr/bin/python2.4 # # # Copyright 2008, The Android Open Source Project # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Parser for test definition xml files.""" # Python imports import xml.dom.minidom import xml.parsers # local imports import errors import logger import xml_suite_helper class TestDefinitions(object): """Accessor for a test definitions xml file data. See test_defs.xsd for expected format. """ def __init__(self): # dictionary of test name to tests self._testname_map = {} def __iter__(self): ordered_list = [] for k in sorted(self._testname_map): ordered_list.append(self._testname_map[k]) return iter(ordered_list) def Parse(self, file_path): """Parse the test suite data from from given file path. Args: file_path: absolute file path to parse Raises: ParseError if file_path cannot be parsed """ try: doc = xml.dom.minidom.parse(file_path) self._ParseDoc(doc) except IOError: logger.Log("test file %s does not exist" % file_path) raise errors.ParseError except xml.parsers.expat.ExpatError: logger.Log("Error Parsing xml file: %s " % file_path) raise errors.ParseError except errors.ParseError, e: logger.Log("Error Parsing xml file: %s Reason: %s" % (file_path, e.msg)) raise e def ParseString(self, xml_string): """Alternate parse method that accepts a string of the xml data.""" doc = xml.dom.minidom.parseString(xml_string) # TODO: catch exceptions and raise ParseError return self._ParseDoc(doc) def _ParseDoc(self, doc): root_element = self._GetRootElement(doc) suite_parser = xml_suite_helper.XmlSuiteParser() for element in root_element.childNodes: if element.nodeType != xml.dom.Node.ELEMENT_NODE: continue test_suite = suite_parser.Parse(element) if test_suite: self._AddTest(test_suite) def _GetRootElement(self, doc): root_elements = doc.getElementsByTagName("test-definitions") if len(root_elements) != 1: error_msg = "expected 1 and only one test-definitions tag" raise errors.ParseError(msg=error_msg) return root_elements[0] def _AddTest(self, test): """Adds a test to this TestManifest. If a test already exists with the same name, it overrides it. Args: test: TestSuite to add """ if self.GetTest(test.GetName()) is not None: logger.SilentLog("Overriding test definition %s" % test.GetName()) self._testname_map[test.GetName()] = test def GetTests(self): return self._testname_map.values() def GetContinuousTests(self): con_tests = [] for test in self.GetTests(): if test.IsContinuous(): con_tests.append(test) return con_tests def GetTestsInSuite(self, suite): """Return list of tests in given suite.""" return [t for t in self.GetTests() if t.GetSuite() == suite] def GetTest(self, name): return self._testname_map.get(name, None) def Parse(file_path): """Parses out a TestDefinitions from given path to xml file. Args: file_path: string absolute file path Returns: a TestDefinitions object containing data parsed from file_path Raises: ParseError if xml format is not recognized """ tests_result = TestDefinitions() tests_result.Parse(file_path) return tests_result