def _prepare_environment_for_android(disable_android_setup): """Additional environment overrides needed to run on an Android device.""" environment.set_value('OS_OVERRIDE', 'ANDROID') # Bail out if we don't have an Android device connected. serial = environment.get_value('ANDROID_SERIAL') if not serial: # TODO(mbarbella): Handle the one-device case gracefully. raise errors.ReproduceToolUnrecoverableError( 'This test case requires an Android device. Please set the ' 'ANDROID_SERIAL environment variable and try again.') print('Warning: this tool will make changes to settings on the connected ' 'Android device with serial {serial} that could result in data ' 'loss.'.format(serial=serial)) willing_to_continue = prompts.get_boolean( 'Are you sure you want to continue?') if not willing_to_continue: raise errors.ReproduceToolUnrecoverableError( 'Bailing out to avoid changing settings on the connected device.') # Push the test case and build APK to the device. apk_path = environment.get_value('APP_PATH') device.update_build(apk_path, should_initialize_device=not disable_android_setup) device.push_testcases_to_device()
def prepare_environment(disable_android_setup): """Additional environment overrides needed to run on an Android device.""" environment.set_value('OS_OVERRIDE', 'ANDROID') # Bail out if we can't determine which Android device to use. serial = environment.get_value('ANDROID_SERIAL') if not serial: devices = get_devices() if len(devices) == 1: serial = devices[0] environment.set_value('ANDROID_SERIAL', serial) elif not devices: raise errors.ReproduceToolUnrecoverableError( 'No connected Android devices were detected. Run with the -e ' 'argument to use an emulator.') else: raise errors.ReproduceToolUnrecoverableError( 'You have multiple Android devices or emulators connected. Please ' 'set the ANDROID_SERIAL environment variable and try again.\n\n' 'Attached devices: ' + ', '.join(devices)) print('Warning: this tool will make changes to settings on the connected ' 'Android device with serial {serial} that could result in data ' 'loss.'.format(serial=serial)) willing_to_continue = prompts.get_boolean( 'Are you sure you want to continue?') if not willing_to_continue: raise errors.ReproduceToolUnrecoverableError( 'Bailing out to avoid changing settings on the connected device.') # Push the test case and build APK to the device. apk_path = environment.get_value('APP_PATH') device.update_build(apk_path, should_initialize_device=not disable_android_setup) device.push_testcases_to_device()
def _reproduce_crash( testcase_url, build_directory, iterations, disable_xvfb, verbose, disable_android_setup, ): """Reproduce a crash.""" _prepare_initial_environment(build_directory, iterations, verbose) # Validate the test case URL and fetch the tool's configuration. testcase_id = _get_testcase_id_from_url(testcase_url) configuration = config.ReproduceToolConfiguration(testcase_url) testcase = _get_testcase(testcase_id, configuration) # For new user uploads, we'll fail without the metadata set by analyze task. if not testcase.platform: raise errors.ReproduceToolUnrecoverableError( "This test case has not yet been processed. Please try again later." ) # Ensure that we support this test case's platform. if testcase.platform not in SUPPORTED_PLATFORMS: raise errors.ReproduceToolUnrecoverableError( "The reproduce tool is not yet supported on {platform}.".format( platform=testcase.platform)) # Print warnings for this test case. if testcase.one_time_crasher_flag: print("Warning: this test case was a one-time crash. It may not be " "reproducible.") if testcase.flaky_stack: print("Warning: this test case is known to crash with different stack " "traces.") testcase_path = _download_testcase(testcase_id, testcase, configuration) _update_environment_for_testcase(testcase, build_directory) # Validate that we're running on the right platform for this test case. platform = environment.platform().lower() if testcase.platform == "android" and platform == "linux": android.prepare_environment(disable_android_setup) elif testcase.platform == "android" and platform != "linux": raise errors.ReproduceToolUnrecoverableError( "The ClusterFuzz environment only supports running Android test cases " "on Linux host machines. Unable to reproduce the test case on " "{current_platform}.".format(current_platform=platform)) elif testcase.platform != platform: raise errors.ReproduceToolUnrecoverableError( "The specified test case was discovered on {testcase_platform}. " "Unable to attempt to reproduce it on {current_platform}.".format( testcase_platform=testcase.platform, current_platform=platform)) x_processes = [] if not disable_xvfb: _setup_x() timeout = environment.get_value("TEST_TIMEOUT") print("Running testcase...") try: result = testcase_manager.test_for_crash_with_retries(testcase, testcase_path, timeout, crash_retries=1) # If we can't reproduce the crash, prompt the user to try again. if not result.is_crash(): _print_stacktrace(result) result = None use_default_retries = prompts.get_boolean( "Failed to find the desired crash on first run. Re-run " "{crash_retries} times?".format( crash_retries=environment.get_value("CRASH_RETRIES"))) if use_default_retries: print( "Attempting to reproduce test case. This may take a while..." ) result = testcase_manager.test_for_crash_with_retries( testcase, testcase_path, timeout) except KeyboardInterrupt: print("Aborting...") result = None # Terminate Xvfb and blackbox. for process in x_processes: process.terminate() return result