Home | History | Annotate | Download | only in utils
      1 # SPDX-License-Identifier: Apache-2.0
      2 #
      3 # Copyright (C) 2015, ARM Limited and contributors.
      4 #
      5 # Licensed under the Apache License, Version 2.0 (the "License"); you may
      6 # not use this file except in compliance with the License.
      7 # You may obtain a copy of the License at
      8 #
      9 # http://www.apache.org/licenses/LICENSE-2.0
     10 #
     11 # Unless required by applicable law or agreed to in writing, software
     12 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
     13 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14 # See the License for the specific language governing permissions and
     15 # limitations under the License.
     16 #
     17 
     18 import os
     19 
     20 SCRIPT_NAME = 'remote_script.sh'
     21 
     22 class TargetScript(object):
     23     """
     24     This class provides utility to create and run a script
     25     directly on a devlib target.
     26 
     27     The execute() method is made to look like Devlib's, so a Target instance can
     28     be swapped with an instance of this TargetScript class, and the commands
     29     will be accumulated for later use instead of being executed straight away.
     30 
     31     :param env: Reference TestEnv instance. Will be used for some commands
     32         that must really be executed instead of accumulated.
     33     :type env: TestEnv
     34 
     35     :param script_name: Name of the script that will be pushed on the target,
     36         defaults to "remote_script.sh"
     37     :type script_name: str
     38     """
     39 
     40     _target_attrs = ['screen_resolution', 'android_id', 'abi', 'os_version', 'model']
     41 
     42     def __init__(self, env, script_name=SCRIPT_NAME):
     43         self._env = env
     44         self._target = env.target
     45         self._script_name = script_name
     46         self.commands = []
     47         
     48     # This is made to look like the devlib Target execute()
     49     def execute(self, cmd):
     50         """
     51         Accumulate command for later execution.
     52 
     53         :param cmd: Command that would be run on the target
     54         :type cmd: str
     55         """
     56         self.append(cmd)
     57 
     58     def append(self, cmd):
     59         """
     60         Append a command to the script.
     61 
     62         :param cmd: Command string to append
     63         :type cmd: str
     64         """
     65         self.commands.append(cmd)
     66 
     67     # Some commands may require some info about the real target.
     68     # For instance, System.{h,v}swipe needs to get the value of
     69     # screen_resolution to generate a swipe command at a given
     70     # screen coordinate percentage.
     71     # Thus, if such a property is called on this object,
     72     # it will be fetched from the 'real' target object.
     73     def __getattr__(self, name):
     74         if name in self._target_attrs:
     75             return getattr(self._target, name)
     76 
     77         return getattr(super, name)
     78             
     79     def push(self):
     80         """
     81         Push a script to the target
     82 
     83         The script is created and stored on the host,
     84         and is then sent to the target.
     85 
     86         :param path: Path where the script will be locally created
     87         :type path: str
     88         :param actions: List of actions(commands) to run
     89         :type actions: list(str)
     90         """
     91 
     92         actions = ['set -e'] + self.commands + ['set +e']
     93         actions = ['#!{} sh'.format(self._target.busybox)] + actions
     94         actions = str.join('\n', actions)
     95 
     96         self._remote_path = self._target.path.join(self._target.executables_directory,
     97                                                    self._script_name)
     98         self._local_path = os.path.join(self._env.res_dir, self._script_name)
     99 
    100         # Create script locally
    101         with open(self._local_path, 'w') as script:
    102             script.write(actions)
    103 
    104         # Push it on target
    105         self._target.push(self._local_path, self._remote_path)
    106         self._target.execute('chmod +x {}'.format(self._remote_path))
    107 
    108     def run(self):
    109         """
    110         Run the previously pushed script
    111         """
    112 
    113         if self._target.file_exists(self._remote_path):
    114             self._target.execute(self._remote_path)
    115         else:
    116             raise IOError('Remote script was not found on target device')
    117