Home | History | Annotate | Download | only in test_defs
      1 #!/usr/bin/python2.4
      2 #
      3 #
      4 # Copyright 2008, The Android Open Source Project
      5 #
      6 # Licensed under the Apache License, Version 2.0 (the "License");
      7 # you may not use this file except in compliance with the License.
      8 # You may obtain a copy of the License at
      9 #
     10 #     http://www.apache.org/licenses/LICENSE-2.0
     11 #
     12 # Unless required by applicable law or agreed to in writing, software
     13 # distributed under the License is distributed on an "AS IS" BASIS,
     14 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     15 # See the License for the specific language governing permissions and
     16 # limitations under the License.
     17 
     18 """Parser for test definition xml files."""
     19 
     20 # Python imports
     21 import xml.dom.minidom
     22 import xml.parsers
     23 
     24 # local imports
     25 import errors
     26 import logger
     27 import xml_suite_helper
     28 
     29 
     30 class TestDefinitions(object):
     31   """Accessor for a test definitions xml file data.
     32 
     33   See test_defs.xsd for expected format.
     34   """
     35 
     36   def __init__(self):
     37     # dictionary of test name to tests
     38     self._testname_map = {}
     39 
     40   def __iter__(self):
     41     ordered_list = []
     42     for k in sorted(self._testname_map):
     43       ordered_list.append(self._testname_map[k])
     44     return iter(ordered_list)
     45 
     46   def Parse(self, file_path):
     47     """Parse the test suite data from from given file path.
     48 
     49     Args:
     50       file_path: absolute file path to parse
     51     Raises:
     52       ParseError if file_path cannot be parsed
     53     """
     54     try:
     55       doc = xml.dom.minidom.parse(file_path)
     56       self._ParseDoc(doc)
     57     except IOError:
     58       logger.Log("test file %s does not exist" % file_path)
     59       raise errors.ParseError
     60     except xml.parsers.expat.ExpatError:
     61       logger.Log("Error Parsing xml file: %s " %  file_path)
     62       raise errors.ParseError
     63     except errors.ParseError, e:
     64       logger.Log("Error Parsing xml file: %s Reason: %s" %  (file_path, e.msg))
     65       raise e
     66 
     67   def ParseString(self, xml_string):
     68     """Alternate parse method that accepts a string of the xml data."""
     69     doc = xml.dom.minidom.parseString(xml_string)
     70     # TODO: catch exceptions and raise ParseError
     71     return self._ParseDoc(doc)
     72 
     73   def _ParseDoc(self, doc):
     74     root_element = self._GetRootElement(doc)
     75     suite_parser = xml_suite_helper.XmlSuiteParser()
     76     for element in root_element.childNodes:
     77       if element.nodeType != xml.dom.Node.ELEMENT_NODE:
     78         continue
     79       test_suite = suite_parser.Parse(element)
     80       if test_suite:
     81         self._AddTest(test_suite)
     82 
     83   def _GetRootElement(self, doc):
     84     root_elements = doc.getElementsByTagName("test-definitions")
     85     if len(root_elements) != 1:
     86       error_msg = "expected 1 and only one test-definitions tag"
     87       raise errors.ParseError(msg=error_msg)
     88     return root_elements[0]
     89 
     90   def _AddTest(self, test):
     91     """Adds a test to this TestManifest.
     92 
     93     If a test already exists with the same name, it overrides it.
     94 
     95     Args:
     96       test: TestSuite to add
     97     """
     98     if self.GetTest(test.GetName()) is not None:
     99       logger.SilentLog("Overriding test definition %s" % test.GetName())
    100     self._testname_map[test.GetName()] = test
    101 
    102   def GetTests(self):
    103     return self._testname_map.values()
    104 
    105   def GetContinuousTests(self):
    106     con_tests = []
    107     for test in self.GetTests():
    108       if test.IsContinuous():
    109         con_tests.append(test)
    110     return con_tests
    111 
    112   def GetTestsInSuite(self, suite):
    113     """Return list of tests in given suite."""
    114     return [t for t in self.GetTests() if t.GetSuite() == suite]
    115 
    116   def GetTest(self, name):
    117     return self._testname_map.get(name, None)
    118 
    119 
    120 def Parse(file_path):
    121   """Parses out a TestDefinitions from given path to xml file.
    122 
    123   Args:
    124     file_path: string absolute file path
    125   Returns:
    126     a TestDefinitions object containing data parsed from file_path
    127   Raises:
    128     ParseError if xml format is not recognized
    129   """
    130   tests_result = TestDefinitions()
    131   tests_result.Parse(file_path)
    132   return tests_result
    133