am 3447c407: Merge change I8f6ac3c9 into eclair
Merge commit '3447c407dc70a365d6d7faade0f3725315d05e54' into eclair-mr2 * commit '3447c407dc70a365d6d7faade0f3725315d05e54': Refactor runtest test_defs to allow programmatic creation.
This commit is contained in:
@@ -1,113 +0,0 @@
|
|||||||
#!/usr/bin/python2.4
|
|
||||||
#
|
|
||||||
#
|
|
||||||
# Copyright 2009, 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.
|
|
||||||
|
|
||||||
"""Abstract Android test suite."""
|
|
||||||
|
|
||||||
# Python imports
|
|
||||||
import xml.dom.minidom
|
|
||||||
import xml.parsers
|
|
||||||
|
|
||||||
# local imports
|
|
||||||
import errors
|
|
||||||
|
|
||||||
|
|
||||||
class AbstractTestSuite(object):
|
|
||||||
"""Represents a generic test suite definition parsed from xml.
|
|
||||||
|
|
||||||
This class will parse the XML attributes common to all TestSuite's.
|
|
||||||
"""
|
|
||||||
|
|
||||||
# name of xml tag a test suite handles. subclasses must define this.
|
|
||||||
TAG_NAME = "unspecified"
|
|
||||||
|
|
||||||
_NAME_ATTR = "name"
|
|
||||||
_BUILD_ATTR = "build_path"
|
|
||||||
_CONTINUOUS_ATTR = "continuous"
|
|
||||||
_CTS_ATTR = "cts"
|
|
||||||
_DESCRIPTION_ATTR = "description"
|
|
||||||
_EXTRA_BUILD_ARGS_ATTR = "extra_build_args"
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
self._attr_map = {}
|
|
||||||
|
|
||||||
def Parse(self, suite_element):
|
|
||||||
"""Populates this instance's data from given suite xml element.
|
|
||||||
Raises:
|
|
||||||
ParseError if a required attribute is missing.
|
|
||||||
"""
|
|
||||||
# parse name first so it can be used for error reporting
|
|
||||||
self._ParseAttribute(suite_element, self._NAME_ATTR, True)
|
|
||||||
self._ParseAttribute(suite_element, self._BUILD_ATTR, True)
|
|
||||||
self._ParseAttribute(suite_element, self._CONTINUOUS_ATTR, False,
|
|
||||||
default_value=False)
|
|
||||||
self._ParseAttribute(suite_element, self._CTS_ATTR, False,
|
|
||||||
default_value=False)
|
|
||||||
self._ParseAttribute(suite_element, self._DESCRIPTION_ATTR, False,
|
|
||||||
default_value="")
|
|
||||||
self._ParseAttribute(suite_element, self._EXTRA_BUILD_ARGS_ATTR, False,
|
|
||||||
default_value="")
|
|
||||||
|
|
||||||
def _ParseAttribute(self, suite_element, attribute_name, mandatory,
|
|
||||||
default_value=None):
|
|
||||||
if suite_element.hasAttribute(attribute_name):
|
|
||||||
self._attr_map[attribute_name] = \
|
|
||||||
suite_element.getAttribute(attribute_name)
|
|
||||||
elif mandatory:
|
|
||||||
error_msg = ("Could not find attribute %s in %s %s" %
|
|
||||||
(attribute_name, self.TAG_NAME, self.GetName()))
|
|
||||||
raise errors.ParseError(msg=error_msg)
|
|
||||||
else:
|
|
||||||
self._attr_map[attribute_name] = default_value
|
|
||||||
|
|
||||||
def GetName(self):
|
|
||||||
return self._GetAttribute(self._NAME_ATTR)
|
|
||||||
|
|
||||||
def GetBuildPath(self):
|
|
||||||
"""Returns the build path of this test, relative to source tree root."""
|
|
||||||
return self._GetAttribute(self._BUILD_ATTR)
|
|
||||||
|
|
||||||
def GetBuildDependencies(self, options):
|
|
||||||
"""Returns a list of dependent build paths."""
|
|
||||||
return []
|
|
||||||
|
|
||||||
def IsContinuous(self):
|
|
||||||
"""Returns true if test is flagged as being part of the continuous tests"""
|
|
||||||
return self._GetAttribute(self._CONTINUOUS_ATTR)
|
|
||||||
|
|
||||||
def IsCts(self):
|
|
||||||
"""Returns true if test is part of the compatibility test suite"""
|
|
||||||
return self._GetAttribute(self._CTS_ATTR)
|
|
||||||
|
|
||||||
def GetDescription(self):
|
|
||||||
"""Returns a description if available, an empty string otherwise."""
|
|
||||||
return self._GetAttribute(self._DESCRIPTION_ATTR)
|
|
||||||
|
|
||||||
def GetExtraBuildArgs(self):
|
|
||||||
"""Returns the extra build args if available, an empty string otherwise."""
|
|
||||||
return self._GetAttribute(self._EXTRA_BUILD_ARGS_ATTR)
|
|
||||||
|
|
||||||
def _GetAttribute(self, attribute_name):
|
|
||||||
return self._attr_map.get(attribute_name)
|
|
||||||
|
|
||||||
def Run(self, options, adb):
|
|
||||||
"""Runs the test.
|
|
||||||
|
|
||||||
Subclasses must implement this.
|
|
||||||
Args:
|
|
||||||
options: global command line options
|
|
||||||
"""
|
|
||||||
raise NotImplementedError
|
|
||||||
@@ -20,23 +20,15 @@
|
|||||||
# python imports
|
# python imports
|
||||||
import os
|
import os
|
||||||
|
|
||||||
# local imports
|
|
||||||
from abstract_test import AbstractTestSuite
|
|
||||||
import errors
|
import errors
|
||||||
import logger
|
import logger
|
||||||
import run_command
|
import run_command
|
||||||
|
import test_suite
|
||||||
|
|
||||||
|
|
||||||
class HostTestSuite(AbstractTestSuite):
|
class HostTestSuite(test_suite.AbstractTestSuite):
|
||||||
"""A test suite for running hosttestlib java tests."""
|
"""A test suite for running hosttestlib java tests."""
|
||||||
|
|
||||||
TAG_NAME = "test-host"
|
|
||||||
|
|
||||||
_CLASS_ATTR = "class"
|
|
||||||
# TODO: consider obsoleting in favor of parsing the Android.mk to find the
|
|
||||||
# jar name
|
|
||||||
_JAR_ATTR = "jar_name"
|
|
||||||
|
|
||||||
_JUNIT_JAR_NAME = "junit.jar"
|
_JUNIT_JAR_NAME = "junit.jar"
|
||||||
_HOSTTESTLIB_NAME = "hosttestlib.jar"
|
_HOSTTESTLIB_NAME = "hosttestlib.jar"
|
||||||
_DDMLIB_NAME = "ddmlib.jar"
|
_DDMLIB_NAME = "ddmlib.jar"
|
||||||
@@ -54,21 +46,29 @@ class HostTestSuite(AbstractTestSuite):
|
|||||||
# the test suite?
|
# the test suite?
|
||||||
_TEST_RUNNER = "com.android.hosttest.DeviceTestRunner"
|
_TEST_RUNNER = "com.android.hosttest.DeviceTestRunner"
|
||||||
|
|
||||||
def Parse(self, suite_element):
|
def __init__(self):
|
||||||
super(HostTestSuite, self).Parse(suite_element)
|
test_suite.AbstractTestSuite.__init__(self)
|
||||||
self._ParseAttribute(suite_element, self._CLASS_ATTR, True)
|
self._jar_name = None
|
||||||
self._ParseAttribute(suite_element, self._JAR_ATTR, True)
|
self._class_name = None
|
||||||
|
|
||||||
def GetBuildDependencies(self, options):
|
def GetBuildDependencies(self, options):
|
||||||
"""Override parent to tag on building host libs."""
|
"""Override parent to tag on building host libs."""
|
||||||
return self._LIB_BUILD_PATHS
|
return self._LIB_BUILD_PATHS
|
||||||
|
|
||||||
def GetClass(self):
|
def GetClassName(self):
|
||||||
return self._GetAttribute(self._CLASS_ATTR)
|
return self._class_name
|
||||||
|
|
||||||
|
def SetClassName(self, class_name):
|
||||||
|
self._class_name = class_name
|
||||||
|
return self
|
||||||
|
|
||||||
def GetJarName(self):
|
def GetJarName(self):
|
||||||
"""Returns the name of the host jar that contains the tests."""
|
"""Returns the name of the host jar that contains the tests."""
|
||||||
return self._GetAttribute(self._JAR_ATTR)
|
return self._jar_name
|
||||||
|
|
||||||
|
def SetJarName(self, jar_name):
|
||||||
|
self._jar_name = jar_name
|
||||||
|
return self
|
||||||
|
|
||||||
def Run(self, options, adb_interface):
|
def Run(self, options, adb_interface):
|
||||||
"""Runs the host test.
|
"""Runs the host test.
|
||||||
@@ -82,6 +82,9 @@ class HostTestSuite(AbstractTestSuite):
|
|||||||
test_data_path: path to directory that contains test data files
|
test_data_path: path to directory that contains test data files
|
||||||
preview: if true, do not execute, display commands only
|
preview: if true, do not execute, display commands only
|
||||||
adb_interface: reference to device under test
|
adb_interface: reference to device under test
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
errors.AbortError: if fatal error occurs
|
||||||
"""
|
"""
|
||||||
# get the serial number of the device under test, so it can be passed to
|
# get the serial number of the device under test, so it can be passed to
|
||||||
# hosttestlib.
|
# hosttestlib.
|
||||||
@@ -100,7 +103,7 @@ class HostTestSuite(AbstractTestSuite):
|
|||||||
# -p <test data path>
|
# -p <test data path>
|
||||||
cmd = "java -cp %s %s %s -s %s -p %s" % (":".join(full_lib_paths),
|
cmd = "java -cp %s %s %s -s %s -p %s" % (":".join(full_lib_paths),
|
||||||
self._TEST_RUNNER,
|
self._TEST_RUNNER,
|
||||||
self.GetClass(), serial_number,
|
self.GetClassName(), serial_number,
|
||||||
options.test_data_path)
|
options.test_data_path)
|
||||||
logger.Log(cmd)
|
logger.Log(cmd)
|
||||||
if not options.preview:
|
if not options.preview:
|
||||||
|
|||||||
@@ -21,59 +21,66 @@
|
|||||||
import os
|
import os
|
||||||
|
|
||||||
# local imports
|
# local imports
|
||||||
from abstract_test import AbstractTestSuite
|
|
||||||
import coverage
|
import coverage
|
||||||
import errors
|
import errors
|
||||||
import logger
|
import logger
|
||||||
|
import test_suite
|
||||||
|
|
||||||
|
|
||||||
class InstrumentationTestSuite(AbstractTestSuite):
|
class InstrumentationTestSuite(test_suite.AbstractTestSuite):
|
||||||
"""Represents a java instrumentation test suite definition run on Android device."""
|
"""Represents a java instrumentation test suite definition run on device."""
|
||||||
|
|
||||||
# for legacy reasons, the xml tag name for java (device) tests is "test:
|
DEFAULT_RUNNER = "android.test.InstrumentationTestRunner"
|
||||||
TAG_NAME = "test"
|
|
||||||
|
|
||||||
_PKG_ATTR = "package"
|
|
||||||
_RUNNER_ATTR = "runner"
|
|
||||||
_CLASS_ATTR = "class"
|
|
||||||
_TARGET_ATTR = "coverage_target"
|
|
||||||
|
|
||||||
_DEFAULT_RUNNER = "android.test.InstrumentationTestRunner"
|
|
||||||
|
|
||||||
# build path to Emma target Makefile
|
# build path to Emma target Makefile
|
||||||
_EMMA_BUILD_PATH = os.path.join("external", "emma")
|
_EMMA_BUILD_PATH = os.path.join("external", "emma")
|
||||||
|
|
||||||
def _GetTagName(self):
|
def __init__(self):
|
||||||
return self._TAG_NAME
|
test_suite.AbstractTestSuite.__init__(self)
|
||||||
|
self._package_name = None
|
||||||
|
self._runner_name = self.DEFAULT_RUNNER
|
||||||
|
self._class_name = None
|
||||||
|
self._target_name = None
|
||||||
|
|
||||||
def GetPackageName(self):
|
def GetPackageName(self):
|
||||||
return self._GetAttribute(self._PKG_ATTR)
|
return self._package_name
|
||||||
|
|
||||||
|
def SetPackageName(self, package_name):
|
||||||
|
self._package_name = package_name
|
||||||
|
return self
|
||||||
|
|
||||||
def GetRunnerName(self):
|
def GetRunnerName(self):
|
||||||
return self._GetAttribute(self._RUNNER_ATTR)
|
return self._runner_name
|
||||||
|
|
||||||
|
def SetRunnerName(self, runner_name):
|
||||||
|
self._runner_name = runner_name
|
||||||
|
return self
|
||||||
|
|
||||||
def GetClassName(self):
|
def GetClassName(self):
|
||||||
return self._GetAttribute(self._CLASS_ATTR)
|
return self._class_name
|
||||||
|
|
||||||
|
def SetClassName(self, class_name):
|
||||||
|
self._class_name = class_name
|
||||||
|
return self
|
||||||
|
|
||||||
def GetTargetName(self):
|
def GetTargetName(self):
|
||||||
"""Retrieve module that this test is targeting.
|
"""Retrieve module that this test is targeting.
|
||||||
|
|
||||||
Used for generating code coverage metrics.
|
Used for generating code coverage metrics.
|
||||||
|
Returns:
|
||||||
|
the module target name
|
||||||
"""
|
"""
|
||||||
return self._GetAttribute(self._TARGET_ATTR)
|
return self._target_name
|
||||||
|
|
||||||
|
def SetTargetName(self, target_name):
|
||||||
|
self._target_name = target_name
|
||||||
|
return self
|
||||||
|
|
||||||
def GetBuildDependencies(self, options):
|
def GetBuildDependencies(self, options):
|
||||||
if options.coverage:
|
if options.coverage:
|
||||||
return [self._EMMA_BUILD_PATH]
|
return [self._EMMA_BUILD_PATH]
|
||||||
return []
|
return []
|
||||||
|
|
||||||
def Parse(self, suite_element):
|
|
||||||
super(InstrumentationTestSuite, self).Parse(suite_element)
|
|
||||||
self._ParseAttribute(suite_element, self._PKG_ATTR, True)
|
|
||||||
self._ParseAttribute(suite_element, self._RUNNER_ATTR, False, self._DEFAULT_RUNNER)
|
|
||||||
self._ParseAttribute(suite_element, self._CLASS_ATTR, False)
|
|
||||||
self._ParseAttribute(suite_element, self._TARGET_ATTR, False)
|
|
||||||
|
|
||||||
def Run(self, options, adb):
|
def Run(self, options, adb):
|
||||||
"""Run the provided test suite.
|
"""Run the provided test suite.
|
||||||
|
|
||||||
@@ -82,6 +89,9 @@ class InstrumentationTestSuite(AbstractTestSuite):
|
|||||||
Args:
|
Args:
|
||||||
options: command line options to provide to test run
|
options: command line options to provide to test run
|
||||||
adb: adb_interface to device under test
|
adb: adb_interface to device under test
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
errors.AbortError: if fatal error occurs
|
||||||
"""
|
"""
|
||||||
|
|
||||||
test_class = self.GetClassName()
|
test_class = self.GetClassName()
|
||||||
|
|||||||
@@ -18,28 +18,19 @@
|
|||||||
"""TestSuite for running native Android tests."""
|
"""TestSuite for running native Android tests."""
|
||||||
|
|
||||||
# python imports
|
# python imports
|
||||||
import re
|
|
||||||
import os
|
import os
|
||||||
|
import re
|
||||||
|
|
||||||
# local imports
|
# local imports
|
||||||
from abstract_test import AbstractTestSuite
|
|
||||||
import android_build
|
import android_build
|
||||||
import logger
|
import logger
|
||||||
import run_command
|
import run_command
|
||||||
|
import test_suite
|
||||||
|
|
||||||
|
|
||||||
class NativeTestSuite(AbstractTestSuite):
|
class NativeTestSuite(test_suite.AbstractTestSuite):
|
||||||
"""A test suite for running native aka C/C++ tests on device."""
|
"""A test suite for running native aka C/C++ tests on device."""
|
||||||
|
|
||||||
TAG_NAME = "test-native"
|
|
||||||
|
|
||||||
def _GetTagName(self):
|
|
||||||
return self._TAG_NAME
|
|
||||||
|
|
||||||
def Parse(self, suite_element):
|
|
||||||
super(NativeTestSuite, self).Parse(suite_element)
|
|
||||||
|
|
||||||
|
|
||||||
def Run(self, options, adb):
|
def Run(self, options, adb):
|
||||||
"""Run the provided *native* test suite.
|
"""Run the provided *native* test suite.
|
||||||
|
|
||||||
|
|||||||
@@ -24,9 +24,7 @@ import xml.parsers
|
|||||||
# local imports
|
# local imports
|
||||||
import errors
|
import errors
|
||||||
import logger
|
import logger
|
||||||
from instrumentation_test import InstrumentationTestSuite
|
import xml_suite_helper
|
||||||
from native_test import NativeTestSuite
|
|
||||||
from host_test import HostTestSuite
|
|
||||||
|
|
||||||
|
|
||||||
class TestDefinitions(object):
|
class TestDefinitions(object):
|
||||||
@@ -74,20 +72,12 @@ class TestDefinitions(object):
|
|||||||
|
|
||||||
def _ParseDoc(self, doc):
|
def _ParseDoc(self, doc):
|
||||||
root_element = self._GetRootElement(doc)
|
root_element = self._GetRootElement(doc)
|
||||||
|
suite_parser = xml_suite_helper.XmlSuiteParser()
|
||||||
for element in root_element.childNodes:
|
for element in root_element.childNodes:
|
||||||
if element.nodeType != xml.dom.Node.ELEMENT_NODE:
|
if element.nodeType != xml.dom.Node.ELEMENT_NODE:
|
||||||
continue
|
continue
|
||||||
test_suite = None
|
test_suite = suite_parser.Parse(element)
|
||||||
if element.nodeName == InstrumentationTestSuite.TAG_NAME:
|
if test_suite:
|
||||||
test_suite = InstrumentationTestSuite()
|
|
||||||
elif element.nodeName == NativeTestSuite.TAG_NAME:
|
|
||||||
test_suite = NativeTestSuite()
|
|
||||||
elif element.nodeName == HostTestSuite.TAG_NAME:
|
|
||||||
test_suite = HostTestSuite()
|
|
||||||
else:
|
|
||||||
logger.Log("Unrecognized tag %s found" % element.nodeName)
|
|
||||||
continue
|
|
||||||
test_suite.Parse(element)
|
|
||||||
self._AddTest(test_suite)
|
self._AddTest(test_suite)
|
||||||
|
|
||||||
def _GetRootElement(self, doc):
|
def _GetRootElement(self, doc):
|
||||||
|
|||||||
96
testrunner/test_defs/test_suite.py
Normal file
96
testrunner/test_defs/test_suite.py
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
#!/usr/bin/python2.4
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# Copyright 2009, 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.
|
||||||
|
|
||||||
|
"""Abstract Android test suite."""
|
||||||
|
|
||||||
|
|
||||||
|
class AbstractTestSuite(object):
|
||||||
|
"""Represents a generic test suite definition."""
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self._name = None
|
||||||
|
self._build_path = None
|
||||||
|
self._build_dependencies = []
|
||||||
|
self._is_continuous = False
|
||||||
|
self._is_cts = False
|
||||||
|
self._description = ''
|
||||||
|
self._extra_build_args = ''
|
||||||
|
|
||||||
|
def GetName(self):
|
||||||
|
return self._name
|
||||||
|
|
||||||
|
def SetName(self, name):
|
||||||
|
self._name = name
|
||||||
|
return self
|
||||||
|
|
||||||
|
def GetBuildPath(self):
|
||||||
|
"""Returns the build path of this test, relative to source tree root."""
|
||||||
|
return self._build_path
|
||||||
|
|
||||||
|
def SetBuildPath(self, build_path):
|
||||||
|
self._build_path = build_path
|
||||||
|
return self
|
||||||
|
|
||||||
|
def GetBuildDependencies(self, options):
|
||||||
|
"""Returns a list of dependent build paths."""
|
||||||
|
return self._build_dependencies
|
||||||
|
|
||||||
|
def SetBuildDependencies(self, build_dependencies):
|
||||||
|
self._build_dependencies = build_dependencies
|
||||||
|
return self
|
||||||
|
|
||||||
|
def IsContinuous(self):
|
||||||
|
"""Returns true if test is part of the continuous test."""
|
||||||
|
return self._is_continuous
|
||||||
|
|
||||||
|
def SetContinuous(self, continuous):
|
||||||
|
self._is_continuous = continuous
|
||||||
|
return self._is_continuous
|
||||||
|
|
||||||
|
def IsCts(self):
|
||||||
|
"""Returns true if test is part of the compatibility test suite"""
|
||||||
|
return self._is_cts
|
||||||
|
|
||||||
|
def SetCts(self, cts):
|
||||||
|
self._is_cts = cts
|
||||||
|
return self
|
||||||
|
|
||||||
|
def GetDescription(self):
|
||||||
|
"""Returns a description if available, an empty string otherwise."""
|
||||||
|
return self._description
|
||||||
|
|
||||||
|
def SetDescription(self, desc):
|
||||||
|
self._description = desc
|
||||||
|
return self
|
||||||
|
|
||||||
|
def GetExtraBuildArgs(self):
|
||||||
|
"""Returns the extra build args if available, an empty string otherwise."""
|
||||||
|
return self._extra_build_args
|
||||||
|
|
||||||
|
def SetExtraBuildArgs(self, build_args):
|
||||||
|
self._extra_build_args = build_args
|
||||||
|
return self
|
||||||
|
|
||||||
|
def Run(self, options, adb):
|
||||||
|
"""Runs the test.
|
||||||
|
|
||||||
|
Subclasses must implement this.
|
||||||
|
Args:
|
||||||
|
options: global command line options
|
||||||
|
adb: asdb_interface to device under test
|
||||||
|
"""
|
||||||
|
raise NotImplementedError
|
||||||
152
testrunner/test_defs/xml_suite_helper.py
Normal file
152
testrunner/test_defs/xml_suite_helper.py
Normal file
@@ -0,0 +1,152 @@
|
|||||||
|
#!/usr/bin/python2.4
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# Copyright 2009, 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.
|
||||||
|
|
||||||
|
"""Utility to parse suite info from xml."""
|
||||||
|
|
||||||
|
# Python imports
|
||||||
|
import xml.dom.minidom
|
||||||
|
import xml.parsers
|
||||||
|
|
||||||
|
# local imports
|
||||||
|
import errors
|
||||||
|
import logger
|
||||||
|
import host_test
|
||||||
|
import instrumentation_test
|
||||||
|
import native_test
|
||||||
|
|
||||||
|
|
||||||
|
class XmlSuiteParser(object):
|
||||||
|
"""Parses XML attributes common to all TestSuite's."""
|
||||||
|
|
||||||
|
# common attributes
|
||||||
|
_NAME_ATTR = 'name'
|
||||||
|
_BUILD_ATTR = 'build_path'
|
||||||
|
_CONTINUOUS_ATTR = 'continuous'
|
||||||
|
_CTS_ATTR = 'cts'
|
||||||
|
_DESCRIPTION_ATTR = 'description'
|
||||||
|
_EXTRA_BUILD_ARGS_ATTR = 'extra_build_args'
|
||||||
|
|
||||||
|
def Parse(self, element):
|
||||||
|
"""Populates common suite attributes from given suite xml element.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
element: xml node to parse
|
||||||
|
Raises:
|
||||||
|
ParseError if a required attribute is missing.
|
||||||
|
Returns:
|
||||||
|
parsed test suite or None
|
||||||
|
"""
|
||||||
|
parser = None
|
||||||
|
if element.nodeName == InstrumentationParser.TAG_NAME:
|
||||||
|
parser = InstrumentationParser()
|
||||||
|
elif element.nodeName == NativeParser.TAG_NAME:
|
||||||
|
parser = NativeParser()
|
||||||
|
elif element.nodeName == HostParser.TAG_NAME:
|
||||||
|
parser = HostParser()
|
||||||
|
else:
|
||||||
|
logger.Log('Unrecognized tag %s found' % element.nodeName)
|
||||||
|
return None
|
||||||
|
test_suite = parser.Parse(element)
|
||||||
|
return test_suite
|
||||||
|
|
||||||
|
def _ParseCommonAttributes(self, suite_element, test_suite):
|
||||||
|
test_suite.SetName(self._ParseAttribute(suite_element, self._NAME_ATTR,
|
||||||
|
True))
|
||||||
|
test_suite.SetBuildPath(self._ParseAttribute(suite_element,
|
||||||
|
self._BUILD_ATTR, True))
|
||||||
|
test_suite.SetContinuous(self._ParseAttribute(suite_element,
|
||||||
|
self._CONTINUOUS_ATTR,
|
||||||
|
False, default_value=False))
|
||||||
|
test_suite.SetCts(self._ParseAttribute(suite_element, self._CTS_ATTR, False,
|
||||||
|
default_value=False))
|
||||||
|
test_suite.SetDescription(self._ParseAttribute(suite_element,
|
||||||
|
self._DESCRIPTION_ATTR,
|
||||||
|
False,
|
||||||
|
default_value=''))
|
||||||
|
test_suite.SetExtraBuildArgs(self._ParseAttribute(
|
||||||
|
suite_element, self._EXTRA_BUILD_ARGS_ATTR, False, default_value=''))
|
||||||
|
|
||||||
|
def _ParseAttribute(self, suite_element, attribute_name, mandatory,
|
||||||
|
default_value=None):
|
||||||
|
if suite_element.hasAttribute(attribute_name):
|
||||||
|
value = suite_element.getAttribute(attribute_name)
|
||||||
|
elif mandatory:
|
||||||
|
error_msg = ('Could not find attribute %s in %s' %
|
||||||
|
(attribute_name, self.TAG_NAME))
|
||||||
|
raise errors.ParseError(msg=error_msg)
|
||||||
|
else:
|
||||||
|
value = default_value
|
||||||
|
return value
|
||||||
|
|
||||||
|
|
||||||
|
class InstrumentationParser(XmlSuiteParser):
|
||||||
|
"""Parses instrumentation suite attributes from xml."""
|
||||||
|
|
||||||
|
# for legacy reasons, the xml tag name for java (device) tests is 'test'
|
||||||
|
TAG_NAME = 'test'
|
||||||
|
|
||||||
|
_PKG_ATTR = 'package'
|
||||||
|
_RUNNER_ATTR = 'runner'
|
||||||
|
_CLASS_ATTR = 'class'
|
||||||
|
_TARGET_ATTR = 'coverage_target'
|
||||||
|
|
||||||
|
def Parse(self, suite_element):
|
||||||
|
"""Creates suite and populate with data from xml element."""
|
||||||
|
suite = instrumentation_test.InstrumentationTestSuite()
|
||||||
|
XmlSuiteParser._ParseCommonAttributes(self, suite_element, suite)
|
||||||
|
suite.SetPackageName(self._ParseAttribute(suite_element, self._PKG_ATTR,
|
||||||
|
True))
|
||||||
|
suite.SetRunnerName(self._ParseAttribute(
|
||||||
|
suite_element, self._RUNNER_ATTR, False,
|
||||||
|
instrumentation_test.InstrumentationTestSuite.DEFAULT_RUNNER))
|
||||||
|
suite.SetClassName(self._ParseAttribute(suite_element, self._CLASS_ATTR,
|
||||||
|
False))
|
||||||
|
suite.SetTargetName(self._ParseAttribute(suite_element, self._TARGET_ATTR,
|
||||||
|
False))
|
||||||
|
return suite
|
||||||
|
|
||||||
|
|
||||||
|
class NativeParser(XmlSuiteParser):
|
||||||
|
"""Parses native suite attributes from xml."""
|
||||||
|
|
||||||
|
TAG_NAME = 'test-native'
|
||||||
|
|
||||||
|
def Parse(self, suite_element):
|
||||||
|
"""Creates suite and populate with data from xml element."""
|
||||||
|
suite = native_test.NativeTestSuite()
|
||||||
|
XmlSuiteParser._ParseCommonAttributes(self, suite_element, suite)
|
||||||
|
return suite
|
||||||
|
|
||||||
|
|
||||||
|
class HostParser(XmlSuiteParser):
|
||||||
|
"""Parses host suite attributes from xml."""
|
||||||
|
|
||||||
|
TAG_NAME = 'test-host'
|
||||||
|
|
||||||
|
_CLASS_ATTR = 'class'
|
||||||
|
# TODO: consider obsoleting in favor of parsing the Android.mk to find the
|
||||||
|
# jar name
|
||||||
|
_JAR_ATTR = 'jar_name'
|
||||||
|
|
||||||
|
def Parse(self, suite_element):
|
||||||
|
"""Creates suite and populate with data from xml element."""
|
||||||
|
suite = host_test.HostTestSuite()
|
||||||
|
XmlSuiteParser._ParseCommonAttributes(self, suite_element, suite)
|
||||||
|
suite.SetClassName(self._ParseAttribute(suite_element, self._CLASS_ATTR,
|
||||||
|
True))
|
||||||
|
suite.SetJarName(self._ParseAttribute(suite_element, self._JAR_ATTR, True))
|
||||||
|
return suite
|
||||||
Reference in New Issue
Block a user