def run_raptor(self, **kwargs): build_obj = self is_android = Conditions.is_android(build_obj) or \ kwargs['app'] in FIREFOX_ANDROID_BROWSERS if is_android: from mozrunner.devices.android_device import ( verify_android_device, InstallIntent) from mozdevice import ADBAndroid, ADBHost install = InstallIntent.NO if kwargs.pop( 'noinstall', False) else InstallIntent.PROMPT if not verify_android_device( build_obj, install=install, app=kwargs['binary'], xre=True): # Equivalent to 'run_local' = True. return 1 debug_command = '--debug-command' if debug_command in sys.argv: sys.argv.remove(debug_command) raptor = self._spawn(RaptorRunner) try: if is_android and kwargs['power_test']: device = ADBAndroid(verbose=True) adbhost = ADBHost(verbose=True) device_serial = "{}:5555".format(device.get_ip_address()) device.command_output(["tcpip", "5555"]) six.input( "Please disconnect your device from USB then press Enter/return..." ) adbhost.command_output(["connect", device_serial]) while len(adbhost.devices()) > 1: six.input( "You must disconnect your device from USB before continuing." ) # must reset the environment DEVICE_SERIAL which was set during # verify_android_device to match our new tcpip value. os.environ["DEVICE_SERIAL"] = device_serial return raptor.run_test(sys.argv[2:], kwargs) except Exception as e: print(repr(e)) return 1 finally: try: if is_android and kwargs['power_test']: six.input( "Connect device via USB and press Enter/return...") device = ADBAndroid(device=device_serial, verbose=True) device.command_output(["usb"]) adbhost.command_output(["disconnect", device_serial]) except Exception: adbhost.command_output(["kill-server"])
def run_raptor_test(self, **kwargs): build_obj = MozbuildObject.from_environment(cwd=HERE) firefox_android_browsers = ["fennec", "geckoview", "refbrow", "fenix"] if conditions.is_android( build_obj) or kwargs['app'] in firefox_android_browsers: from mozrunner.devices.android_device import verify_android_device from mozdevice import ADBAndroid, ADBHost if not verify_android_device( build_obj, install=True, app=kwargs['binary'], xre=True): # Equivalent to 'run_local' = True. return 1 debug_command = '--debug-command' if debug_command in sys.argv: sys.argv.remove(debug_command) raptor = self._spawn(RaptorRunner) try: if kwargs['app'] in firefox_android_browsers and kwargs[ 'power_test']: device = ADBAndroid(verbose=True) adbhost = ADBHost(verbose=True) device_serial = "%s:5555" % device.get_ip_address() device.command_output(["tcpip", "5555"]) raw_input( "Please disconnect your device from USB then press Enter/return..." ) adbhost.command_output(["connect", device_serial]) while len(adbhost.devices()) > 1: raw_input( "You must disconnect your device from USB before continuing." ) # must reset the environment DEVICE_SERIAL which was set during # verify_android_device to match our new tcpip value. os.environ["DEVICE_SERIAL"] = device_serial return raptor.run_test(sys.argv[2:], kwargs) except Exception as e: print(repr(e)) return 1 finally: try: if kwargs['app'] in firefox_android_browsers and kwargs[ 'power_test']: raw_input( "Connect device via USB and press Enter/return...") device = ADBAndroid(device=device_serial, verbose=True) device.command_output(["usb"]) adbhost.command_output(["disconnect", device_serial]) except Exception: adbhost.command_output(["kill-server"])
def main(): parser = argparse.ArgumentParser( usage='%(prog)s [options] <test command> (<test command option> ...)', description="Wrapper script for tests run on physical Android devices at Bitbar. Runs the provided command " "wrapped with required setup and teardown.") _args, extra_args = parser.parse_known_args() logging.basicConfig(format='%(asctime)-15s %(levelname)s %(message)s', level=logging.INFO, stream=sys.stdout) print('\nscript.py: starting') with open('/builds/worker/version') as versionfile: version = versionfile.read().strip() print('\nDockerfile version {}'.format(version)) taskcluster_debug = '*' task_cwd = os.getcwd() print('Current working directory: {}'.format(task_cwd)) with open('/builds/taskcluster/scriptvars.json') as scriptvars: scriptvarsenv = json.loads(scriptvars.read()) print('Bitbar test run: https://mozilla.testdroid.com/#testing/device-session/{}/{}/{}'.format( scriptvarsenv['TESTDROID_PROJECT_ID'], scriptvarsenv['TESTDROID_BUILD_ID'], scriptvarsenv['TESTDROID_RUN_ID'])) env = dict(os.environ) if 'PATH' in os.environ: path = os.environ['PATH'] else: path = '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin' path += ':/builds/worker/android-sdk-linux/tools/bin:/builds/worker/android-sdk-linux/platform-tools' env['PATH'] = os.environ['PATH'] = path env['NEED_XVFB'] = 'false' env['DEVICE_NAME'] = scriptvarsenv['DEVICE_NAME'] env['ANDROID_DEVICE'] = scriptvarsenv['ANDROID_DEVICE'] env['DEVICE_SERIAL'] = scriptvarsenv['DEVICE_SERIAL'] env['HOST_IP'] = scriptvarsenv['HOST_IP'] env['DEVICE_IP'] = scriptvarsenv['DEVICE_IP'] env['DOCKER_IMAGE_VERSION'] = scriptvarsenv['DOCKER_IMAGE_VERSION'] if 'HOME' not in env: env['HOME'] = '/builds/worker' print('setting HOME to {}'.format(env['HOME'])) show_df() # If we are running normal tests we will be connected via usb and # there should be only one device connected. If we are running # power tests, the framework will have already called adb tcpip # 5555 on the device before it disconnected usb. There should be # no devices connected and we will need to perform an adb connect # to connect to the device. DEVICE_SERIAL will be set to either # the device's serial number or its ipaddress:5555 by the framework. try: adbhost = ADBHost(verbose=True) if env['DEVICE_SERIAL'].endswith(':5555'): # Power testing with adb over wifi. adbhost.command_output(["connect", env['DEVICE_SERIAL']]) devices = adbhost.devices() print(json.dumps(devices, indent=4)) if len(devices) != 1: fatal('Must have exactly one connected device. {} found.'.format(len(devices)), retry=True) except (ADBError, ADBTimeoutError) as e: fatal('{} Unable to obtain attached devices'.format(e), retry=True) try: for f in glob('/tmp/adb.*.log'): print('\n{}:\n'.format(f)) with open(f) as afile: print(afile.read()) except Exception as e: print('{} while reading adb logs'.format(e)) print('Connecting to Android device {}'.format(env['DEVICE_SERIAL'])) try: device = ADBDevice(device=env['DEVICE_SERIAL']) android_version = device.get_prop('ro.build.version.release') print('Android device version (ro.build.version.release): {}'.format(android_version)) # this can explode if an unknown device, explode now vs in an hour... device_type = get_device_type(device) # set device to UTC if device.is_rooted: device.shell_output('setprop persist.sys.timezone "UTC"', timeout=ADB_COMMAND_TIMEOUT) # show date for visual confirmation device_datetime = device.shell_output("date", timeout=ADB_COMMAND_TIMEOUT) print('Android device datetime: {}'.format(device_datetime)) # clean up the device. device.rm('/data/local/tests', recursive=True, force=True) device.rm('/data/local/tmp/*', recursive=True, force=True) device.rm('/data/local/tmp/xpcb', recursive=True, force=True) device.rm('/sdcard/tests', recursive=True, force=True) device.rm('/sdcard/raptor-profile', recursive=True, force=True) except (ADBError, ADBTimeoutError) as e: fatal("{} attempting to clean up device".format(e), retry=True) if taskcluster_debug: env['DEBUG'] = taskcluster_debug print('environment = {}'.format(json.dumps(env, indent=4))) # run the payload's command and ensure that: # - all output is printed # - no deadlock occurs between proc.poll() and sys.stdout.readline() # - more info # - https://bugzilla.mozilla.org/show_bug.cgi?id=1611936 # - https://stackoverflow.com/questions/58471094/python-subprocess-readline-hangs-cant-use-normal-options print("script.py: running command '%s'" % ' '.join(extra_args)) rc = None proc = subprocess.Popen(extra_args, # use standard os buffer size bufsize=-1, env=env, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, close_fds=True) # Create the queue instance q = queue.Queue() # Kick off the monitoring thread thread = threading.Thread(target=_monitor_readline, args=(proc, q)) thread.daemon = True thread.start() start = datetime.now() while True: time.sleep(0.1) bail = True rc = proc.poll() if rc is None: bail = False # Re-set the thread timer start = datetime.now() out = "" while not q.empty(): out += q.get() if out: print(out.rstrip()) # In the case where the thread is still alive and reading, and # the process has exited and finished, give it up to X seconds # to finish reading if bail and thread.is_alive() and (datetime.now() - start).total_seconds() < 5: bail = False if bail: break print("script.py: command finished") # enable charging on device if it is disabled # see https://bugzilla.mozilla.org/show_bug.cgi?id=1565324 enable_charging(device, device_type) try: if env['DEVICE_SERIAL'].endswith(':5555'): device.command_output(["usb"]) adbhost.command_output(["disconnect", env['DEVICE_SERIAL']]) adbhost.kill_server() except (ADBError, ADBTimeoutError) as e: print('{} attempting adb kill-server'.format(e)) try: print('\nnetstat -aop\n%s\n\n' % subprocess.check_output( ['netstat', '-aop'], stderr=subprocess.STDOUT).decode()) except subprocess.CalledProcessError as e: print('{} attempting netstat'.format(e)) show_df() print('script.py: exiting with exitcode {}.'.format(rc)) return rc
def main(): parser = argparse.ArgumentParser( usage='%(prog)s [options] <test command> (<test command option> ...)', description= "Wrapper script for tests run on physical Android devices at Bitbar. Runs the provided command wrapped with required setup and teardown." ) _args, extra_args = parser.parse_known_args() logging.basicConfig(format='%(asctime)-15s %(levelname)s %(message)s', level=logging.INFO, stream=sys.stdout) print('\nBegin script.py') with open('/builds/worker/version') as versionfile: version = versionfile.read().strip() print('\nDockerfile version {}'.format(version)) taskcluster_debug = '*' task_cwd = os.getcwd() print('Current working directory: {}'.format(task_cwd)) with open('/builds/taskcluster/scriptvars.json') as scriptvars: scriptvarsenv = json.loads(scriptvars.read()) print( 'Bitbar test run: https://mozilla.testdroid.com/#testing/device-session/{}/{}/{}' .format(scriptvarsenv['TESTDROID_PROJECT_ID'], scriptvarsenv['TESTDROID_BUILD_ID'], scriptvarsenv['TESTDROID_RUN_ID'])) env = dict(os.environ) if 'PATH' in os.environ: path = os.environ['PATH'] else: path = '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin' path += ':/builds/worker/android-sdk-linux/tools/bin:/builds/worker/android-sdk-linux/platform-tools' env['PATH'] = os.environ['PATH'] = path env['NEED_XVFB'] = 'false' env['DEVICE_NAME'] = scriptvarsenv['DEVICE_NAME'] env['ANDROID_DEVICE'] = scriptvarsenv['ANDROID_DEVICE'] env['DEVICE_SERIAL'] = scriptvarsenv['DEVICE_SERIAL'] env['HOST_IP'] = scriptvarsenv['HOST_IP'] env['DEVICE_IP'] = scriptvarsenv['DEVICE_IP'] env['DOCKER_IMAGE_VERSION'] = scriptvarsenv['DOCKER_IMAGE_VERSION'] if 'HOME' not in env: env['HOME'] = '/builds/worker' print('setting HOME to {}'.format(env['HOME'])) # If we are running normal tests we will be connected via usb and # there should be only one device connected. If we are running # power tests, the framework will have already called adb tcpip # 5555 on the device before it disconnected usb. There should be # no devices connected and we will need to perform an adb connect # to connect to the device. DEVICE_SERIAL will be set to either # the device's serial number or its ipaddress:5555 by the framework. try: adbhost = ADBHost() if env['DEVICE_SERIAL'].endswith(':5555'): # Power testing with adb over wifi. adbhost.command_output(["connect", env['DEVICE_SERIAL']]) devices = adbhost.devices() print(json.dumps(devices, indent=4)) if len(devices) != 1: fatal('Must have exactly one connected device. {} found.'.format( len(devices))) except ADBError as e: fatal('{} Unable to obtain attached devices'.format(e)) try: for f in glob('/tmp/adb.*.log'): print('\n{}:\n'.format(f)) with open(f) as afile: print(afile.read()) except Exception as e: print('{} while reading adb logs'.format(e)) print('Connecting to Android device {}'.format(env['DEVICE_SERIAL'])) try: device = ADBDevice(device=env['DEVICE_SERIAL']) android_version = device.get_prop('ro.build.version.release') print('Android device version (ro.build.version.release): {}'.format( android_version)) # this can explode if an unknown device, explode now vs in an hour... device_type = get_device_type(device) # clean up the device. device.rm('/data/local/tests', recursive=True, force=True, root=True) device.rm('/data/local/tmp/*', recursive=True, force=True, root=True) device.rm('/data/local/tmp/xpcb', recursive=True, force=True, root=True) device.rm('/sdcard/tests', recursive=True, force=True, root=True) device.rm('/sdcard/raptor-profile', recursive=True, force=True, root=True) except ADBError as e: fatal("{} attempting to clean up device".format(e)) if taskcluster_debug: env['DEBUG'] = taskcluster_debug print('environment = {}'.format(json.dumps(env, indent=4))) # run the payload's command print(' '.join(extra_args)) rc = None proc = subprocess.Popen(extra_args, env=env, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) while rc == None: line = proc.stdout.readline() sys.stdout.write(line) rc = proc.poll() # enable charging on device if it is disabled # see https://bugzilla.mozilla.org/show_bug.cgi?id=1565324 enable_charging(device, device_type) try: if env['DEVICE_SERIAL'].endswith(':5555'): device.command_output(["usb"]) adbhost.command_output(["disconnect", env['DEVICE_SERIAL']]) adbhost.kill_server() except ADBError as e: print('{} attempting adb kill-server'.format(e)) try: print('\nnetstat -aop\n%s\n\n' % subprocess.check_output( ['netstat', '-aop'], stderr=subprocess.STDOUT)) except subprocess.CalledProcessError as e: print('{} attempting netstat'.format(e)) print('script.py exitcode {}'.format(rc)) return rc