blob: 949ad6ef815a9e201134a90de9c843f228d968a4 [file] [log] [blame]
The Android Open Source Project52d4c302009-03-03 19:29:09 -08001#!/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
The Android Open Source Project2b83cbd2009-03-05 17:04:45 -080018"""Parser for test definition xml files."""
19
The Android Open Source Project52d4c302009-03-03 19:29:09 -080020# Python imports
21import xml.dom.minidom
22import xml.parsers
The Android Open Source Project52d4c302009-03-03 19:29:09 -080023
24# local imports
The Android Open Source Project52d4c302009-03-03 19:29:09 -080025import errors
The Android Open Source Project2b83cbd2009-03-05 17:04:45 -080026import logger
27
The Android Open Source Project52d4c302009-03-03 19:29:09 -080028
29class TestDefinitions(object):
The Android Open Source Project2b83cbd2009-03-05 17:04:45 -080030 """Accessor for a test definitions xml file data.
31
32 Expected format is:
33 <test-definitions>
34 <test
35 name=""
36 package=""
37 [runner=""]
38 [class=""]
39 [coverage_target=""]
40 [build_path=""]
41 [continuous]
42 />
43 <test ...
44 </test-definitions>
45
46 TODO: add format checking.
The Android Open Source Project52d4c302009-03-03 19:29:09 -080047 """
48
49 # tag/attribute constants
The Android Open Source Project2b83cbd2009-03-05 17:04:45 -080050 _TEST_TAG_NAME = "test"
The Android Open Source Project52d4c302009-03-03 19:29:09 -080051
The Android Open Source Project2b83cbd2009-03-05 17:04:45 -080052 def __init__(self):
The Android Open Source Project52d4c302009-03-03 19:29:09 -080053 # dictionary of test name to tests
54 self._testname_map = {}
The Android Open Source Project2b83cbd2009-03-05 17:04:45 -080055
The Android Open Source Project52d4c302009-03-03 19:29:09 -080056 def __iter__(self):
57 return iter(self._testname_map.values())
The Android Open Source Project2b83cbd2009-03-05 17:04:45 -080058
The Android Open Source Project52d4c302009-03-03 19:29:09 -080059 def Parse(self, file_path):
The Android Open Source Project2b83cbd2009-03-05 17:04:45 -080060 """Parse the test suite data from from given file path.
61
62 Args:
63 file_path: absolute file path to parse
64 Raises:
65 ParseError if file_path cannot be parsed
66 """
The Android Open Source Project52d4c302009-03-03 19:29:09 -080067 try:
68 doc = xml.dom.minidom.parse(file_path)
69 except IOError:
The Android Open Source Project2b83cbd2009-03-05 17:04:45 -080070 logger.Log("test file %s does not exist" % file_path)
The Android Open Source Project52d4c302009-03-03 19:29:09 -080071 raise errors.ParseError
72 except xml.parsers.expat.ExpatError:
The Android Open Source Project2b83cbd2009-03-05 17:04:45 -080073 logger.Log("Error Parsing xml file: %s " % file_path)
The Android Open Source Project52d4c302009-03-03 19:29:09 -080074 raise errors.ParseError
The Android Open Source Project2b83cbd2009-03-05 17:04:45 -080075 self._ParseDoc(doc)
76
The Android Open Source Project52d4c302009-03-03 19:29:09 -080077 def ParseString(self, xml_string):
The Android Open Source Project2b83cbd2009-03-05 17:04:45 -080078 """Alternate parse method that accepts a string of the xml data."""
The Android Open Source Project52d4c302009-03-03 19:29:09 -080079 doc = xml.dom.minidom.parseString(xml_string)
80 # TODO: catch exceptions and raise ParseError
The Android Open Source Project2b83cbd2009-03-05 17:04:45 -080081 return self._ParseDoc(doc)
The Android Open Source Project52d4c302009-03-03 19:29:09 -080082
The Android Open Source Project2b83cbd2009-03-05 17:04:45 -080083 def _ParseDoc(self, doc):
The Android Open Source Project52d4c302009-03-03 19:29:09 -080084 suite_elements = doc.getElementsByTagName(self._TEST_TAG_NAME)
85
86 for suite_element in suite_elements:
87 test = self._ParseTestSuite(suite_element)
88 self._AddTest(test)
The Android Open Source Project2b83cbd2009-03-05 17:04:45 -080089
The Android Open Source Project52d4c302009-03-03 19:29:09 -080090 def _ParseTestSuite(self, suite_element):
The Android Open Source Project2b83cbd2009-03-05 17:04:45 -080091 """Parse the suite element.
92
93 Returns:
94 a TestSuite object, populated with parsed data
95 """
The Android Open Source Project52d4c302009-03-03 19:29:09 -080096 test = TestSuite(suite_element)
The Android Open Source Project2b83cbd2009-03-05 17:04:45 -080097 return test
98
The Android Open Source Project52d4c302009-03-03 19:29:09 -080099 def _AddTest(self, test):
The Android Open Source Project2b83cbd2009-03-05 17:04:45 -0800100 """Adds a test to this TestManifest.
The Android Open Source Project52d4c302009-03-03 19:29:09 -0800101
The Android Open Source Project2b83cbd2009-03-05 17:04:45 -0800102 If a test already exists with the same name, it overrides it.
103
104 Args:
105 test: TestSuite to add
106 """
107 self._testname_map[test.GetName()] = test
108
The Android Open Source Project52d4c302009-03-03 19:29:09 -0800109 def GetTests(self):
110 return self._testname_map.values()
The Android Open Source Project2b83cbd2009-03-05 17:04:45 -0800111
The Android Open Source Project52d4c302009-03-03 19:29:09 -0800112 def GetContinuousTests(self):
113 con_tests = []
114 for test in self.GetTests():
115 if test.IsContinuous():
116 con_tests.append(test)
The Android Open Source Project2b83cbd2009-03-05 17:04:45 -0800117 return con_tests
118
The Android Open Source Project52d4c302009-03-03 19:29:09 -0800119 def GetTest(self, name):
The Android Open Source Project2b83cbd2009-03-05 17:04:45 -0800120 return self._testname_map.get(name, None)
The Android Open Source Project52d4c302009-03-03 19:29:09 -0800121
The Android Open Source Project2b83cbd2009-03-05 17:04:45 -0800122class TestSuite(object):
123 """Represents one test suite definition parsed from xml."""
124
125 _NAME_ATTR = "name"
126 _PKG_ATTR = "package"
127 _RUNNER_ATTR = "runner"
128 _CLASS_ATTR = "class"
129 _TARGET_ATTR = "coverage_target"
130 _BUILD_ATTR = "build_path"
131 _CONTINUOUS_ATTR = "continuous"
132
133 _DEFAULT_RUNNER = "android.test.InstrumentationTestRunner"
134
The Android Open Source Project52d4c302009-03-03 19:29:09 -0800135 def __init__(self, suite_element):
The Android Open Source Project2b83cbd2009-03-05 17:04:45 -0800136 """Populates this instance's data from given suite xml element."""
The Android Open Source Project52d4c302009-03-03 19:29:09 -0800137 self._name = suite_element.getAttribute(self._NAME_ATTR)
138 self._package = suite_element.getAttribute(self._PKG_ATTR)
139 if suite_element.hasAttribute(self._RUNNER_ATTR):
140 self._runner = suite_element.getAttribute(self._RUNNER_ATTR)
141 else:
The Android Open Source Project2b83cbd2009-03-05 17:04:45 -0800142 self._runner = self._DEFAULT_RUNNER
The Android Open Source Project52d4c302009-03-03 19:29:09 -0800143 if suite_element.hasAttribute(self._CLASS_ATTR):
144 self._class = suite_element.getAttribute(self._CLASS_ATTR)
145 else:
The Android Open Source Project2b83cbd2009-03-05 17:04:45 -0800146 self._class = None
147 if suite_element.hasAttribute(self._TARGET_ATTR):
The Android Open Source Project52d4c302009-03-03 19:29:09 -0800148 self._target_name = suite_element.getAttribute(self._TARGET_ATTR)
149 else:
150 self._target_name = None
The Android Open Source Project2b83cbd2009-03-05 17:04:45 -0800151 if suite_element.hasAttribute(self._BUILD_ATTR):
The Android Open Source Project52d4c302009-03-03 19:29:09 -0800152 self._build_path = suite_element.getAttribute(self._BUILD_ATTR)
153 else:
154 self._build_path = None
The Android Open Source Project2b83cbd2009-03-05 17:04:45 -0800155 if suite_element.hasAttribute(self._CONTINUOUS_ATTR):
The Android Open Source Project52d4c302009-03-03 19:29:09 -0800156 self._continuous = suite_element.getAttribute(self._CONTINUOUS_ATTR)
157 else:
158 self._continuous = False
The Android Open Source Project2b83cbd2009-03-05 17:04:45 -0800159
The Android Open Source Project52d4c302009-03-03 19:29:09 -0800160 def GetName(self):
161 return self._name
The Android Open Source Project2b83cbd2009-03-05 17:04:45 -0800162
The Android Open Source Project52d4c302009-03-03 19:29:09 -0800163 def GetPackageName(self):
164 return self._package
165
166 def GetRunnerName(self):
167 return self._runner
The Android Open Source Project2b83cbd2009-03-05 17:04:45 -0800168
The Android Open Source Project52d4c302009-03-03 19:29:09 -0800169 def GetClassName(self):
170 return self._class
The Android Open Source Project2b83cbd2009-03-05 17:04:45 -0800171
The Android Open Source Project52d4c302009-03-03 19:29:09 -0800172 def GetTargetName(self):
The Android Open Source Project2b83cbd2009-03-05 17:04:45 -0800173 """Retrieve module that this test is targeting.
174
175 Used for generating code coverage metrics.
The Android Open Source Project52d4c302009-03-03 19:29:09 -0800176 """
177 return self._target_name
The Android Open Source Project2b83cbd2009-03-05 17:04:45 -0800178
The Android Open Source Project52d4c302009-03-03 19:29:09 -0800179 def GetBuildPath(self):
The Android Open Source Project2b83cbd2009-03-05 17:04:45 -0800180 """Returns the build path of this test, relative to source tree root."""
The Android Open Source Project52d4c302009-03-03 19:29:09 -0800181 return self._build_path
182
183 def IsContinuous(self):
The Android Open Source Project2b83cbd2009-03-05 17:04:45 -0800184 """Returns true if test is flagged as being part of the continuous tests"""
The Android Open Source Project52d4c302009-03-03 19:29:09 -0800185 return self._continuous
The Android Open Source Project2b83cbd2009-03-05 17:04:45 -0800186
The Android Open Source Project52d4c302009-03-03 19:29:09 -0800187def Parse(file_path):
The Android Open Source Project2b83cbd2009-03-05 17:04:45 -0800188 """Parses out a TestDefinitions from given path to xml file.
189
The Android Open Source Project52d4c302009-03-03 19:29:09 -0800190 Args:
191 file_path: string absolute file path
The Android Open Source Project2b83cbd2009-03-05 17:04:45 -0800192 Returns:
193 a TestDefinitions object containing data parsed from file_path
The Android Open Source Project52d4c302009-03-03 19:29:09 -0800194 Raises:
195 ParseError if xml format is not recognized
196 """
197 tests_result = TestDefinitions()
198 tests_result.Parse(file_path)
199 return tests_result