15d8e4e3581eab9235b8f9c4887f4a7e79f54d769Dan Albertimport time 25d8e4e3581eab9235b8f9c4887f4a7e79f54d769Dan Albert 35d8e4e3581eab9235b8f9c4887f4a7e79f54d769Dan Albertimport libcxx.test.executor 45d8e4e3581eab9235b8f9c4887f4a7e79f54d769Dan Albert 55d8e4e3581eab9235b8f9c4887f4a7e79f54d769Dan Albertfrom libcxx.android import adb 65d8e4e3581eab9235b8f9c4887f4a7e79f54d769Dan Albertfrom lit.util import executeCommand # pylint: disable=import-error 75d8e4e3581eab9235b8f9c4887f4a7e79f54d769Dan Albert 85d8e4e3581eab9235b8f9c4887f4a7e79f54d769Dan Albert 95d8e4e3581eab9235b8f9c4887f4a7e79f54d769Dan Albertclass AdbExecutor(libcxx.test.executor.RemoteExecutor): 105d8e4e3581eab9235b8f9c4887f4a7e79f54d769Dan Albert def __init__(self, serial=None): 115d8e4e3581eab9235b8f9c4887f4a7e79f54d769Dan Albert # TODO(danalbert): Should factor out the shared pieces of SSHExecutor 125d8e4e3581eab9235b8f9c4887f4a7e79f54d769Dan Albert # so we don't have this ugly parent constructor... 135d8e4e3581eab9235b8f9c4887f4a7e79f54d769Dan Albert super(AdbExecutor, self).__init__() 145d8e4e3581eab9235b8f9c4887f4a7e79f54d769Dan Albert self.serial = serial 155d8e4e3581eab9235b8f9c4887f4a7e79f54d769Dan Albert self.local_run = executeCommand 165d8e4e3581eab9235b8f9c4887f4a7e79f54d769Dan Albert 175d8e4e3581eab9235b8f9c4887f4a7e79f54d769Dan Albert def _remote_temp(self, is_dir): 185d8e4e3581eab9235b8f9c4887f4a7e79f54d769Dan Albert dir_arg = '-d' if is_dir else '' 195d8e4e3581eab9235b8f9c4887f4a7e79f54d769Dan Albert cmd = 'mktemp -q {} /data/local/tmp/libcxx.XXXXXXXXXX'.format(dir_arg) 205d8e4e3581eab9235b8f9c4887f4a7e79f54d769Dan Albert temp_path, err, exitCode = self._execute_command_remote([cmd]) 215d8e4e3581eab9235b8f9c4887f4a7e79f54d769Dan Albert temp_path = temp_path.strip() 225d8e4e3581eab9235b8f9c4887f4a7e79f54d769Dan Albert if exitCode != 0: 235d8e4e3581eab9235b8f9c4887f4a7e79f54d769Dan Albert raise RuntimeError(err) 245d8e4e3581eab9235b8f9c4887f4a7e79f54d769Dan Albert return temp_path 255d8e4e3581eab9235b8f9c4887f4a7e79f54d769Dan Albert 265d8e4e3581eab9235b8f9c4887f4a7e79f54d769Dan Albert def _copy_in_file(self, src, dst): # pylint: disable=no-self-use 275d8e4e3581eab9235b8f9c4887f4a7e79f54d769Dan Albert adb.push(src, dst) 285d8e4e3581eab9235b8f9c4887f4a7e79f54d769Dan Albert 295d8e4e3581eab9235b8f9c4887f4a7e79f54d769Dan Albert def _execute_command_remote(self, cmd, remote_work_dir='.', env=None): 305d8e4e3581eab9235b8f9c4887f4a7e79f54d769Dan Albert adb_cmd = ['adb', 'shell'] 315d8e4e3581eab9235b8f9c4887f4a7e79f54d769Dan Albert if self.serial: 325d8e4e3581eab9235b8f9c4887f4a7e79f54d769Dan Albert adb_cmd.extend(['-s', self.serial]) 335d8e4e3581eab9235b8f9c4887f4a7e79f54d769Dan Albert if env: 345d8e4e3581eab9235b8f9c4887f4a7e79f54d769Dan Albert env_cmd = ['env'] + ['%s=%s' % (k, v) for k, v in env.items()] 355d8e4e3581eab9235b8f9c4887f4a7e79f54d769Dan Albert else: 365d8e4e3581eab9235b8f9c4887f4a7e79f54d769Dan Albert env_cmd = [] 375d8e4e3581eab9235b8f9c4887f4a7e79f54d769Dan Albert remote_cmd = ' '.join(env_cmd + cmd + ['; echo $?']) 385d8e4e3581eab9235b8f9c4887f4a7e79f54d769Dan Albert if remote_work_dir != '.': 395d8e4e3581eab9235b8f9c4887f4a7e79f54d769Dan Albert remote_cmd = 'cd {} && {}'.format(remote_work_dir, remote_cmd) 405d8e4e3581eab9235b8f9c4887f4a7e79f54d769Dan Albert adb_cmd.append(remote_cmd) 415d8e4e3581eab9235b8f9c4887f4a7e79f54d769Dan Albert 425d8e4e3581eab9235b8f9c4887f4a7e79f54d769Dan Albert # Tests will commonly fail with ETXTBSY. Possibly related to this bug: 435d8e4e3581eab9235b8f9c4887f4a7e79f54d769Dan Albert # https://code.google.com/p/android/issues/detail?id=65857. Work around 445d8e4e3581eab9235b8f9c4887f4a7e79f54d769Dan Albert # it by just waiting a second and then retrying. 455d8e4e3581eab9235b8f9c4887f4a7e79f54d769Dan Albert for _ in range(10): 465d8e4e3581eab9235b8f9c4887f4a7e79f54d769Dan Albert out, err, exit_code = self.local_run(adb_cmd) 475d8e4e3581eab9235b8f9c4887f4a7e79f54d769Dan Albert if 'Text file busy' in out: 485d8e4e3581eab9235b8f9c4887f4a7e79f54d769Dan Albert time.sleep(1) 495d8e4e3581eab9235b8f9c4887f4a7e79f54d769Dan Albert else: 505d8e4e3581eab9235b8f9c4887f4a7e79f54d769Dan Albert out = out.strip().split('\r\n') 515d8e4e3581eab9235b8f9c4887f4a7e79f54d769Dan Albert status_line = out[-1:][0] 525d8e4e3581eab9235b8f9c4887f4a7e79f54d769Dan Albert out = '\n'.join(out[:-1]) 535d8e4e3581eab9235b8f9c4887f4a7e79f54d769Dan Albert exit_code = int(status_line) 545d8e4e3581eab9235b8f9c4887f4a7e79f54d769Dan Albert break 555d8e4e3581eab9235b8f9c4887f4a7e79f54d769Dan Albert return out, err, exit_code 56