1
0
mirror of https://github.com/ARM-software/workload-automation.git synced 2025-09-04 04:12:42 +01:00

Merge pull request #381 from marcbonnici/revent

Revent & Misc Fixes
This commit is contained in:
setrofim
2017-04-25 10:39:41 +01:00
committed by GitHub
17 changed files with 818 additions and 108 deletions

View File

@@ -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)

View File

@@ -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',

View File

@@ -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()

View File

@@ -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__)

View 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
"""

View File

@@ -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__)

View File

@@ -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.

View File

@@ -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)

View File

@@ -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