mirror of
https://github.com/ARM-software/workload-automation.git
synced 2025-09-04 04:12:42 +01:00
@@ -12,8 +12,7 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
from wlauto.core.configuration.configuration import (settings,
|
||||
RunConfiguration,
|
||||
JobGenerator,
|
||||
ConfigurationPoint)
|
||||
from wlauto.core.configuration.plugin_cache import PluginCache
|
||||
from wa.framework.configuration.core import (settings,
|
||||
RunConfiguration,
|
||||
JobGenerator,
|
||||
ConfigurationPoint)
|
||||
|
@@ -1,7 +1,7 @@
|
||||
from wlauto.core.configuration.configuration import MetaConfiguration, RunConfiguration
|
||||
from wlauto.core.configuration.plugin_cache import PluginCache
|
||||
from wlauto.utils.serializer import yaml
|
||||
from wlauto.utils.doc import strip_inlined_text
|
||||
from wa.framework.configuration.core import MetaConfiguration, RunConfiguration
|
||||
from wa.framework.configuration.plugin_cache import PluginCache
|
||||
from wa.utils.serializer import yaml
|
||||
from wa.utils.doc import strip_inlined_text
|
||||
|
||||
DEFAULT_INSTRUMENTS = ['execution_time',
|
||||
'interrupts',
|
||||
|
@@ -209,7 +209,7 @@ class Executor(object):
|
||||
"""
|
||||
The ``Executor``'s job is to set up the execution context and pass to a
|
||||
``Runner`` along with a loaded run specification. Once the ``Runner`` has
|
||||
done its thing, the ``Executor`` performs some final reporint before
|
||||
done its thing, the ``Executor`` performs some final reporting before
|
||||
returning.
|
||||
|
||||
The initial context set up involves combining configuration from various
|
||||
@@ -225,7 +225,7 @@ class Executor(object):
|
||||
self.error_logged = False
|
||||
self.warning_logged = False
|
||||
pluginloader = None
|
||||
self.device_manager = None
|
||||
self.target_manager = None
|
||||
self.device = None
|
||||
|
||||
def execute(self, config_manager, output):
|
||||
@@ -249,12 +249,12 @@ class Executor(object):
|
||||
output.write_config(config)
|
||||
|
||||
self.logger.info('Connecting to target')
|
||||
target_manager = TargetManager(config.run_config.device,
|
||||
self.target_manager = TargetManager(config.run_config.device,
|
||||
config.run_config.device_config)
|
||||
output.write_target_info(target_manager.get_target_info())
|
||||
output.write_target_info(self.target_manager.get_target_info())
|
||||
|
||||
self.logger.info('Initializing execution conetext')
|
||||
context = ExecutionContext(config_manager, target_manager, output)
|
||||
context = ExecutionContext(config_manager, self.target_manager, output)
|
||||
|
||||
self.logger.info('Generating jobs')
|
||||
config_manager.generate_jobs(context)
|
||||
@@ -262,7 +262,7 @@ class Executor(object):
|
||||
output.write_state()
|
||||
|
||||
self.logger.info('Installing instrumentation')
|
||||
for instrument in config_manager.get_instruments(target_manager.target):
|
||||
for instrument in config_manager.get_instruments(self.target_manager.target):
|
||||
instrumentation.install(instrument)
|
||||
instrumentation.validate()
|
||||
|
||||
@@ -361,6 +361,10 @@ class Runner(object):
|
||||
self.pm.process_run_output(self.context)
|
||||
self.pm.export_run_output(self.context)
|
||||
self.pm.finalize()
|
||||
log.indent()
|
||||
for job in self.context.completed_jobs:
|
||||
job.finalize(self.context)
|
||||
log.dedent()
|
||||
|
||||
def run_next_job(self, context):
|
||||
job = context.start_job()
|
||||
|
@@ -31,7 +31,7 @@ import requests
|
||||
|
||||
from devlib.utils.android import ApkInfo
|
||||
|
||||
from wa import Parameter, settings, __file__ as __base_filepath
|
||||
from wa import Parameter, settings, __file__ as _base_filepath
|
||||
from wa.framework.resource import ResourceGetter, SourcePriority, NO_ONE
|
||||
from wa.framework.exception import ResourceError
|
||||
from wa.utils.misc import (ensure_directory_exists as _d,
|
||||
@@ -80,7 +80,16 @@ def get_from_location(basepath, resource):
|
||||
path = os.path.join(basepath, 'bin', resource.abi, resource.filename)
|
||||
if os.path.exists(path):
|
||||
return path
|
||||
elif resource.kind in ['apk', 'jar', 'revent']:
|
||||
elif resource.kind == 'revent':
|
||||
path = os.path.join(basepath, 'revent_files')
|
||||
if os.path.exists(path):
|
||||
files = get_by_extension(path, resource.kind)
|
||||
found_resource = get_generic_resource(resource, files)
|
||||
if found_resource:
|
||||
return found_resource
|
||||
files = get_by_extension(basepath, resource.kind)
|
||||
return get_generic_resource(resource, files)
|
||||
elif resource.kind in ['apk', 'jar']:
|
||||
files = get_by_extension(basepath, resource.kind)
|
||||
return get_generic_resource(resource, files)
|
||||
|
||||
@@ -96,7 +105,7 @@ class Package(ResourceGetter):
|
||||
|
||||
def get(self, resource):
|
||||
if resource.owner == NO_ONE:
|
||||
basepath = os.path.join(os.path.dirname(__base_filepath), 'assets')
|
||||
basepath = os.path.join(os.path.dirname(_base_filepath), 'assets')
|
||||
else:
|
||||
modname = resource.owner.__module__
|
||||
basepath = os.path.dirname(sys.modules[modname].__file__)
|
||||
|
@@ -1,6 +1,6 @@
|
||||
import os
|
||||
|
||||
from wlauto.core.configuration import settings
|
||||
from wa.framework.configuration.core import settings
|
||||
|
||||
def init_user_directory(overwrite_existing=False): # pylint: disable=R0914
|
||||
"""
|
||||
|
@@ -26,7 +26,7 @@ from itertools import chain
|
||||
from copy import copy
|
||||
|
||||
from wa.framework.configuration.core import settings, ConfigurationPoint as Parameter
|
||||
from wa.framework.exception import (NotFoundError, PluginLoaderError,
|
||||
from wa.framework.exception import (NotFoundError, PluginLoaderError, TargetError,
|
||||
ValidationError, ConfigError, HostError)
|
||||
from wa.utils import log
|
||||
from wa.utils.misc import (ensure_directory_exists as _d, walk_modules, load_class,
|
||||
@@ -430,7 +430,7 @@ class Plugin(object):
|
||||
|
||||
get_module(name, owner, **kwargs)
|
||||
|
||||
and returns an instance of :class:`wlauto.core.plugin.Module`. If the
|
||||
and returns an instance of :class:`wa.core.plugin.Module`. If the
|
||||
module with the specified name is not found, the loader must raise an
|
||||
appropriate exception.
|
||||
|
||||
@@ -743,10 +743,10 @@ class PluginLoader(object):
|
||||
self.logger.warning('Got: {}'.format(e))
|
||||
else:
|
||||
msg = 'Failed to load {}'
|
||||
raise LoaderError(msg.format(filepath), sys.exc_info())
|
||||
raise PluginLoaderError(msg.format(filepath), sys.exc_info())
|
||||
except Exception as e:
|
||||
message = 'Problem loading plugins from {}: {}'
|
||||
raise LoaderError(message.format(filepath, e))
|
||||
raise PluginLoaderError(message.format(filepath, e))
|
||||
|
||||
def _discover_in_module(self, module): # NOQA pylint: disable=too-many-branches
|
||||
self.logger.debug('Checking module %s', module.__name__)
|
||||
|
@@ -231,7 +231,7 @@ def connect(handler, signal, sender=dispatcher.Any, priority=0):
|
||||
|
||||
.. note:: There is nothing that prevents instrumentation from sending their
|
||||
own signals that are not part of the standard set. However the signal
|
||||
must always be an :class:`wlauto.core.signal.Signal` instance.
|
||||
must always be an :class:`wa.core.signal.Signal` instance.
|
||||
|
||||
:sender: The handler will be invoked only for the signals emitted by this sender. By
|
||||
default, this is set to :class:`louie.dispatcher.Any`, so the handler will
|
||||
@@ -270,7 +270,7 @@ def disconnect(handler, signal, sender=dispatcher.Any):
|
||||
|
||||
:handler: The callback to be disconnected.
|
||||
:signal: The signal the handler is to be disconnected form. It will
|
||||
be an :class:`wlauto.core.signal.Signal` instance.
|
||||
be an :class:`wa.core.signal.Signal` instance.
|
||||
:sender: If specified, the handler will only be disconnected from the signal
|
||||
sent by this sender.
|
||||
|
||||
@@ -284,7 +284,7 @@ def send(signal, sender=dispatcher.Anonymous, *args, **kwargs):
|
||||
|
||||
Paramters:
|
||||
|
||||
:signal: Signal to be sent. This must be an instance of :class:`wlauto.core.signal.Signal`
|
||||
:signal: Signal to be sent. This must be an instance of :class:`wa.core.signal.Signal`
|
||||
or its subclasses.
|
||||
:sender: The sender of the signal (typically, this would be ``self``). Some handlers may only
|
||||
be subscribed to signals from a particular sender.
|
||||
|
@@ -33,6 +33,11 @@ def instantiate_target(tdesc, params, connect=None):
|
||||
|
||||
tp, pp, cp = {}, {}, {}
|
||||
|
||||
for supported_params, new_params in (target_params, tp), (platform_params, pp), (conn_params, cp):
|
||||
for name, value in supported_params.iteritems():
|
||||
if value.default:
|
||||
new_params[name] = value.default
|
||||
|
||||
for name, value in params.iteritems():
|
||||
if name in target_params:
|
||||
tp[name] = value
|
||||
@@ -62,6 +67,8 @@ def instantiate_assistant(tdesc, params, target):
|
||||
for param in tdesc.assistant_params:
|
||||
if param.name in params:
|
||||
assistant_params[param.name] = params[param.name]
|
||||
elif param.default:
|
||||
assistant_params[param.name] = param.default
|
||||
return tdesc.assistant(target, **assistant_params)
|
||||
|
||||
|
||||
|
@@ -17,8 +17,11 @@ import os
|
||||
import time
|
||||
|
||||
from wa.framework.plugin import TargetedPlugin
|
||||
from wa.framework.resource import ApkFile, JarFile, ReventFile, NO_ONE
|
||||
from wa.framework.resource import (ApkFile, JarFile, ReventFile, NO_ONE,
|
||||
Executable, File)
|
||||
from wa.framework.exception import WorkloadError
|
||||
from wa.utils.revent import ReventRecorder
|
||||
from wa.utils.exec_control import once
|
||||
|
||||
from devlib.utils.android import ApkInfo
|
||||
|
||||
@@ -64,7 +67,7 @@ class Workload(TargetedPlugin):
|
||||
def run(self, context):
|
||||
"""
|
||||
Execute the workload. This is the method that performs the actual
|
||||
"work" of the.
|
||||
"work" of the workload.
|
||||
"""
|
||||
pass
|
||||
|
||||
@@ -93,25 +96,29 @@ class Workload(TargetedPlugin):
|
||||
return '<Workload {}>'.format(self.name)
|
||||
|
||||
|
||||
class ApkUiautoWorkload(Workload):
|
||||
|
||||
platform = 'android'
|
||||
class ApkUIWorkload(Workload):
|
||||
|
||||
# May be optionally overwritten by subclasses
|
||||
# Times are in seconds
|
||||
loading_time = 10
|
||||
|
||||
def __init__(self, target, **kwargs):
|
||||
super(ApkUiautoWorkload, self).__init__(target, **kwargs)
|
||||
self.apk = ApkHander(self)
|
||||
self.gui = UiAutomatorGUI(self)
|
||||
super(ApkUIWorkload, self).__init__(target, **kwargs)
|
||||
self.apk = None
|
||||
self.gui = None
|
||||
|
||||
def init_resources(self, context):
|
||||
self.apk.init_resources(context.resolver)
|
||||
self.gui.init_resources(context.resolver)
|
||||
self.gui.init_commands()
|
||||
|
||||
@once
|
||||
def initialize(self, context):
|
||||
self.gui.deploy()
|
||||
|
||||
def setup(self, context):
|
||||
self.apk.setup(context)
|
||||
time.sleep(self.loading_time)
|
||||
self.gui.setup()
|
||||
|
||||
def run(self, context):
|
||||
@@ -124,10 +131,40 @@ class ApkUiautoWorkload(Workload):
|
||||
self.gui.teardown()
|
||||
self.apk.teardown()
|
||||
|
||||
@once
|
||||
def finalize(self, context):
|
||||
self.gui.remove()
|
||||
|
||||
|
||||
class ApkUiautoWorkload(ApkUIWorkload):
|
||||
|
||||
platform = 'android'
|
||||
|
||||
def __init__(self, target, **kwargs):
|
||||
super(ApkUiautoWorkload, self).__init__(target, **kwargs)
|
||||
self.apk = ApkHander(self)
|
||||
self.gui = UiAutomatorGUI(self)
|
||||
|
||||
|
||||
class ReventWorkload(ApkUIWorkload):
|
||||
|
||||
# May be optionally overwritten by subclasses
|
||||
# Times are in seconds
|
||||
setup_timeout = 5 * 60
|
||||
run_timeout = 10 * 60
|
||||
extract_results_timeout = 5 * 60
|
||||
teardown_timeout = 5 * 60
|
||||
|
||||
def __init__(self, target, **kwargs):
|
||||
super(ReventWorkload, self).__init__(target, **kwargs)
|
||||
self.apk = ApkHander(self)
|
||||
self.gui = ReventGUI(self, target,
|
||||
self.setup_timeout,
|
||||
self.run_timeout,
|
||||
self.extract_results_timeout,
|
||||
self.teardown_timeout)
|
||||
|
||||
|
||||
class UiAutomatorGUI(object):
|
||||
|
||||
stages = ['setup', 'runWorkload', 'extractResults', 'teardown']
|
||||
@@ -208,57 +245,92 @@ class UiAutomatorGUI(object):
|
||||
|
||||
class ReventGUI(object):
|
||||
|
||||
def __init__(self, workload, target, setup_timeout=5 * 60, run_timeout=10 * 60):
|
||||
def __init__(self, workload, target, setup_timeout, run_timeout,
|
||||
extract_results_timeout, teardown_timeout):
|
||||
self.workload = workload
|
||||
self.target = target
|
||||
self.setup_timeout = setup_timeout
|
||||
self.run_timeout = run_timeout
|
||||
self.extract_results_timeout = extract_results_timeout
|
||||
self.teardown_timeout = teardown_timeout
|
||||
self.revent_recorder = ReventRecorder(self.target)
|
||||
self.on_target_revent_binary = self.target.get_workpath('revent')
|
||||
self.on_target_setup_revent = self.target.get_workpath('{}.setup.revent'.format(self.target.name))
|
||||
self.on_target_run_revent = self.target.get_workpath('{}.run.revent'.format(self.target.name))
|
||||
self.on_target_setup_revent = self.target.get_workpath('{}.setup.revent'.format(self.target.model))
|
||||
self.on_target_run_revent = self.target.get_workpath('{}.run.revent'.format(self.target.model))
|
||||
self.on_target_extract_results_revent = self.target.get_workpath('{}.extract_results.revent'.format(self.target.model))
|
||||
self.on_target_teardown_revent = self.target.get_workpath('{}.teardown.revent'.format(self.target.model))
|
||||
self.logger = logging.getLogger('revent')
|
||||
self.revent_setup_file = None
|
||||
self.revent_run_file = None
|
||||
self.revent_extract_results_file = None
|
||||
self.revent_teardown_file = None
|
||||
|
||||
def init_resources(self, context):
|
||||
self.revent_setup_file = context.resolver.get(ReventFile(self.workload, 'setup'))
|
||||
self.revent_run_file = context.resolver.get(ReventFile(self.workload, 'run'))
|
||||
def init_resources(self, resolver):
|
||||
self.revent_setup_file = resolver.get(ReventFile(owner=self.workload,
|
||||
stage='setup',
|
||||
target=self.target.model),
|
||||
strict=False)
|
||||
self.revent_run_file = resolver.get(ReventFile(owner=self.workload,
|
||||
stage='run',
|
||||
target=self.target.model))
|
||||
self.revent_extract_results_file = resolver.get(ReventFile(owner=self.workload,
|
||||
stage='extract_results',
|
||||
target=self.target.model),
|
||||
strict=False)
|
||||
self.revent_teardown_file = resolver.get(resource=ReventFile(owner=self.workload,
|
||||
stage='teardown',
|
||||
target=self.target.model),
|
||||
strict=False)
|
||||
|
||||
def setup(self, context):
|
||||
self._check_revent_files(context)
|
||||
self.target.killall('revent')
|
||||
command = '{} replay {}'.format(self.on_target_revent_binary, self.on_target_setup_revent)
|
||||
self.target.execute(command, timeout=self.setup_timeout)
|
||||
def deploy(self):
|
||||
self.revent_recorder.deploy()
|
||||
|
||||
def run(self, context):
|
||||
command = '{} replay {}'.format(self.on_target_revent_binary, self.on_target_run_revent)
|
||||
self.logger.debug('Replaying {}'.format(os.path.basename(self.on_target_run_revent)))
|
||||
self.target.execute(command, timeout=self.run_timeout)
|
||||
def setup(self):
|
||||
self._check_revent_files()
|
||||
self.revent_recorder.replay(self.on_target_setup_revent,
|
||||
timeout=self.setup_timeout)
|
||||
|
||||
def run(self):
|
||||
msg = 'Replaying {}'
|
||||
self.logger.debug(msg.format(os.path.basename(self.on_target_run_revent)))
|
||||
self.revent_recorder.replay(self.on_target_run_revent,
|
||||
timeout=self.run_timeout)
|
||||
self.logger.debug('Replay completed.')
|
||||
|
||||
def teardown(self, context):
|
||||
def extract_results(self):
|
||||
if self.revent_extract_results_file:
|
||||
self.revent_recorder.replay(self.on_target_extract_results_revent,
|
||||
timeout=self.extract_results_timeout)
|
||||
|
||||
def teardown(self):
|
||||
if self.revent_teardown_file:
|
||||
self.revent_recorder.replay(self.on_target_teardown_revent,
|
||||
timeout=self.teardown_timeout)
|
||||
self.target.remove(self.on_target_setup_revent)
|
||||
self.target.remove(self.on_target_run_revent)
|
||||
self.target.remove(self.on_target_extract_results_revent)
|
||||
self.target.remove(self.on_target_teardown_revent)
|
||||
|
||||
def _check_revent_files(self, context):
|
||||
# check the revent binary
|
||||
revent_binary = context.resolver.get(Executable(NO_ONE, self.target.abi, 'revent'))
|
||||
if not os.path.isfile(revent_binary):
|
||||
message = '{} does not exist. '.format(revent_binary)
|
||||
message += 'Please build revent for your system and place it in that location'
|
||||
raise WorkloadError(message)
|
||||
if not self.revent_setup_file:
|
||||
# pylint: disable=too-few-format-args
|
||||
message = '{0}.setup.revent file does not exist, Please provide one for your target, {0}'
|
||||
raise WorkloadError(message.format(self.target.name))
|
||||
def remove(self):
|
||||
self.revent_recorder.remove()
|
||||
|
||||
def init_commands(self):
|
||||
pass
|
||||
|
||||
def _check_revent_files(self):
|
||||
if not self.revent_run_file:
|
||||
# pylint: disable=too-few-format-args
|
||||
message = '{0}.run.revent file does not exist, Please provide one for your target, {0}'
|
||||
raise WorkloadError(message.format(self.target.name))
|
||||
message = '{0}.run.revent file does not exist, ' \
|
||||
'Please provide one for your target, {0}'
|
||||
raise WorkloadError(message.format(self.target.model))
|
||||
|
||||
self.on_target_revent_binary = self.target.install(revent_binary)
|
||||
self.target.push(self.revent_run_file, self.on_target_run_revent)
|
||||
self.target.push(self.revent_setup_file, self.on_target_setup_revent)
|
||||
if self.revent_setup_file:
|
||||
self.target.push(self.revent_setup_file, self.on_target_setup_revent)
|
||||
if self.revent_extract_results_file:
|
||||
self.target.push(self.revent_extract_results_file, self.on_target_extract_results_revent)
|
||||
if self.revent_teardown_file:
|
||||
self.target.push(self.revent_teardown_file, self.on_target_teardown_revent)
|
||||
|
||||
|
||||
class ApkHander(object):
|
||||
@@ -280,10 +352,10 @@ class ApkHander(object):
|
||||
self.logcat_log = None
|
||||
|
||||
def init_resources(self, resolver):
|
||||
self.apk_file = resolver.get(ApkFile(self.owner,
|
||||
self.apk_file = resolver.get(ApkFile(self.owner,
|
||||
variant=self.variant,
|
||||
version=self.version),
|
||||
strict=self.strict)
|
||||
version=self.version),
|
||||
strict=self.strict)
|
||||
self.apk_info = ApkInfo(self.apk_file)
|
||||
|
||||
def setup(self, context):
|
||||
@@ -332,7 +404,7 @@ class ApkHander(object):
|
||||
|
||||
def start_activity(self):
|
||||
cmd = 'am start -W -n {}/{}'
|
||||
output = self.target.execute(cmd.format(self.apk_info.package,
|
||||
output = self.target.execute(cmd.format(self.apk_info.package,
|
||||
self.apk_info.activity))
|
||||
if 'Error:' in output:
|
||||
# this will dismiss any error dialogs
|
||||
|
Reference in New Issue
Block a user