blob: d3c5d687531098b8fe058f7bbc1bdcb0c75d5017 [file] [log] [blame]
import time
import libcxx.test.executor
from libcxx.android import adb
from lit.util import executeCommand # pylint: disable=import-error
class AdbExecutor(libcxx.test.executor.RemoteExecutor):
def __init__(self, serial=None):
# TODO(danalbert): Should factor out the shared pieces of SSHExecutor
# so we don't have this ugly parent constructor...
super(AdbExecutor, self).__init__()
self.serial = serial
self.local_run = executeCommand
def _remote_temp(self, is_dir):
dir_arg = '-d' if is_dir else ''
cmd = 'mktemp -q {} /data/local/tmp/libcxx/temp.XXXXXX'.format(dir_arg)
_, temp_path, err, exitCode = self._execute_command_remote([cmd])
temp_path = temp_path.strip()
if exitCode != 0:
raise RuntimeError(err)
return temp_path
def _copy_in_file(self, src, dst): # pylint: disable=no-self-use
adb.push(src, dst)
def _execute_command_remote(self, cmd, remote_work_dir='.', env=None):
adb_cmd = ['adb', 'shell']
if self.serial:
adb_cmd.extend(['-s', self.serial])
delimiter = 'x'
probe_cmd = 'su shell {}; echo {}$?'.format(' '.join(cmd), delimiter)
env_cmd = []
if env is not None:
env_cmd = ['env'] + ['%s=%s' % (k, v) for k, v in env.items()]
remote_cmd = ' '.join(env_cmd + [probe_cmd])
if remote_work_dir != '.':
remote_cmd = 'cd {} && {}'.format(remote_work_dir, remote_cmd)
adb_cmd.append(remote_cmd)
# Tests will commonly fail with ETXTBSY. Possibly related to this bug:
# https://code.google.com/p/android/issues/detail?id=65857. Work around
# it by just waiting a second and then retrying.
for _ in range(10):
out, err, exit_code = self.local_run(adb_cmd)
if 'Text file busy' in out:
time.sleep(1)
else:
out, delim, rc_str = out.rpartition(delimiter)
if delim == '':
continue
out = out.strip()
try:
exit_code = int(rc_str)
break
except ValueError:
continue
return adb_cmd, out, err, exit_code