• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
18import os
19
20SCRIPT_NAME = 'remote_script.sh'
21
22class 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