# SPDX-License-Identifier: Apache-2.0
#
# Copyright (C) 2015, ARM Limited and contributors.
#
# 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.
#
import os
SCRIPT_NAME = 'remote_script.sh'
class TargetScript(object):
"""
This class provides utility to create and run a script
directly on a devlib target.
The execute() method is made to look like Devlib's, so a Target instance can
be swapped with an instance of this TargetScript class, and the commands
will be accumulated for later use instead of being executed straight away.
:param env: Reference TestEnv instance. Will be used for some commands
that must really be executed instead of accumulated.
:type env: TestEnv
:param script_name: Name of the script that will be pushed on the target,
defaults to "remote_script.sh"
:type script_name: str
"""
_target_attrs = ['screen_resolution', 'android_id', 'abi', 'os_version', 'model']
def __init__(self, env, script_name=SCRIPT_NAME):
self._env = env
self._target = env.target
self._script_name = script_name
self.commands = []
# This is made to look like the devlib Target execute()
def execute(self, cmd):
"""
Accumulate command for later execution.
:param cmd: Command that would be run on the target
:type cmd: str
"""
self.append(cmd)
def append(self, cmd):
"""
Append a command to the script.
:param cmd: Command string to append
:type cmd: str
"""
self.commands.append(cmd)
# Some commands may require some info about the real target.
# For instance, System.{h,v}swipe needs to get the value of
# screen_resolution to generate a swipe command at a given
# screen coordinate percentage.
# Thus, if such a property is called on this object,
# it will be fetched from the 'real' target object.
def __getattr__(self, name):
if name in self._target_attrs:
return getattr(self._target, name)
return getattr(super, name)
def push(self):
"""
Push a script to the target
The script is created and stored on the host,
and is then sent to the target.
:param path: Path where the script will be locally created
:type path: str
:param actions: List of actions(commands) to run
:type actions: list(str)
"""
actions = ['set -e'] + self.commands + ['set +e']
actions = ['#!{} sh'.format(self._target.busybox)] + actions
actions = str.join('\n', actions)
self._remote_path = self._target.path.join(self._target.executables_directory,
self._script_name)
self._local_path = os.path.join(self._env.res_dir, self._script_name)
# Create script locally
with open(self._local_path, 'w') as script:
script.write(actions)
# Push it on target
self._target.push(self._local_path, self._remote_path)
self._target.execute('chmod +x {}'.format(self._remote_path))
def run(self):
"""
Run the previously pushed script
"""
if self._target.file_exists(self._remote_path):
self._target.execute(self._remote_path)
else:
raise IOError('Remote script was not found on target device')