def _check_if_packages_exists(test_manifest, test_set_names): found_all_packages = True errors = "" for test_set_name in test_set_names: if test_manifest.contains_set(test_set_name): Printer.system_message( TAG, "Test set " + Color.GREEN + test_set_name + Color.BLUE + " was found in TestManifest. Contains following package names:" ) test_set = test_manifest.get_set(test_set_name) for package_name in test_set.set_package_names: Printer.system_message( TAG, " * " + Color.GREEN + package_name + Color.BLUE) for package_name in test_set.set_package_names: if not test_manifest.contains_package(package_name): found_all_packages = False errors += "\n - Test package '" + package_name + "' was not found in TestManifest!" else: message = "Test set '{}' not found in TestManifest. Launcher will quit." message = message.format(test_set_name) raise LauncherFlowInterruptedException(TAG, message) if found_all_packages: Printer.system_message( TAG, "All test packages were found in TestManifest.") else: raise LauncherFlowInterruptedException(TAG, errors)
def set_instrumentation_runner_according_to(self, apk): Printer.system_message( self.TAG, "Scanning test .*apk file for Instrumentation Runner data.") resources = self.aapt_controller.list_resources(apk.test_apk_path) target_package = "" instrumentation_runner_name = "" inside_instrumentation_section = False inside_manifest_section = False for line in resources.splitlines(): if "E: instrumentation" in line: inside_instrumentation_section = True continue if "E: manifest" in line: inside_manifest_section = True continue if inside_instrumentation_section and "E: " in line: inside_instrumentation_section = False if inside_manifest_section and "E: " in line: inside_manifest_section = False if inside_instrumentation_section: if "A: android:name" in line: regex_result = re.findall("=\"(.+?)\"", line) if regex_result: instrumentation_runner_name = str(regex_result[0]) if inside_manifest_section: if "A: package" in line: regex_result = re.findall("=\"(.+?)\"", line) if regex_result: target_package = str(regex_result[0]) if target_package == "": message = "Unable to find package of tested application in test .*apk file. Tests won't start without it." raise LauncherFlowInterruptedException(self.TAG, message) if instrumentation_runner_name == "": message = ( "Unable to find Instrumentation Runner name of tested application in test .*apk file." " Tests won't start without it.") raise LauncherFlowInterruptedException(self.TAG, message) GlobalConfig.INSTRUMENTATION_RUNNER = target_package + "/" + instrumentation_runner_name Printer.system_message( self.TAG, "Instrumentation Runner found: " + Color.GREEN + GlobalConfig.INSTRUMENTATION_RUNNER + Color.BLUE + ".")
def _check_avd_schema(self): if self.avd_schema.avd_name == "": message = "One AVD schema doesn't have name set." raise LauncherFlowInterruptedException(self.TAG, message) if self.avd_schema.create_avd_package == "": message = "Parameter 'create_avd_package' in AVD schema {} cannot be empty." message = message.format(self.avd_schema.avd_name) raise LauncherFlowInterruptedException(self.TAG, message) if self.avd_schema.launch_avd_launch_binary_name == "": message = "Parameter 'launch_avd_launch_binary_name' in AVD schema {} cannot be empty." message = message.format(self.avd_schema.avd_name) raise LauncherFlowInterruptedException(self.TAG, message)
def install_apk_on_devices(self, apk): if not self.device_store.get_devices(): message = "No devices were found in test session. Launcher will quit." message = message.format(str(GlobalConfig.AVD_SYSTEM_BOOT_TIMEOUT)) raise LauncherFlowInterruptedException(self.TAG, message) self._install_apk(apk)
def prepare_device_directories(self): for device in self.device_store.get_devices(): Printer.system_message( self.TAG, "Checking if folder for test recordings exists on device " + Color.GREEN + device.adb_name + Color.BLUE + ":") result = self.adb_shell_controller.check_for_directory( device.adb_name, GlobalConfig.DEVICE_VIDEO_STORAGE_DIR) if "No such file or directory" in result: Printer.system_message( self.TAG, "Creating directory " + Color.GREEN + GlobalConfig.DEVICE_VIDEO_STORAGE_DIR + Color.BLUE + " directory on device " + Color.GREEN + device.adb_name + Color.BLUE + ".") self.adb_shell_controller.create_dir( device.adb_name, GlobalConfig.DEVICE_VIDEO_STORAGE_DIR) else: Printer.system_message( self.TAG, "Directory " + Color.GREEN + GlobalConfig.DEVICE_VIDEO_STORAGE_DIR + Color.BLUE + " already exists." + " Re-creating.") self.adb_shell_controller.remove_files_in_dir( device.adb_name, GlobalConfig.DEVICE_VIDEO_STORAGE_DIR) self.adb_shell_controller.create_dir( device.adb_name, GlobalConfig.DEVICE_VIDEO_STORAGE_DIR) next_result = self.adb_shell_controller.check_for_directory( device.adb_name, GlobalConfig.DEVICE_VIDEO_STORAGE_DIR) if "No such file or directory" in next_result: message = ( "Directory '" + GlobalConfig.DEVICE_VIDEO_STORAGE_DIR + "' was not created. This will " + "lead to test session to malfunction and crash. Quitting..." ) raise LauncherFlowInterruptedException(self.TAG, message)
def _wait_for_adb_statuses_change_to(self, status, monitored_devices): Printer.system_message( self.TAG, "Waiting until (" + " ".join("'" + device.adb_name + "'" for device in monitored_devices) + ") devices status will change to '" + status + "'.") timeout = GlobalConfig.AVD_ADB_BOOT_TIMEOUT start_time = last_scan_ended = time.time() * 1000 while True: current_time = time.time() * 1000 if current_time - last_scan_ended >= GlobalConfig.ADB_SCAN_INTERVAL or start_time == last_scan_ended: Printer.system_message(self.TAG, "Scanning...") self.device_store.update_model_statuses() Printer.system_message(self.TAG, " * Current wait status:") for device in monitored_devices: Printer.system_message( self.TAG, " " + device.adb_name + " " + Color.GREEN + "('" + device.status + "')") if all(device.status == status for device in monitored_devices): break last_scan_ended = time.time() * 1000 if current_time - start_time >= timeout: message = "Devices took longer than {} seconds to launch (ADB launch). Timeout quit." message = message.format(str(timeout)) raise LauncherFlowInterruptedException(self.TAG, message) Printer.system_message(self.TAG, "ADB wait finished with success!")
def _load_launch_plan(launch_manifest, launch_plan_name): if launch_manifest.contains_plan(launch_plan_name): Printer.system_message(TAG, "Launch plan " + Color.GREEN + launch_plan_name + Color.BLUE + " was found in LaunchManifest.") return launch_manifest.get_plan(launch_plan_name) else: message = "Invalid launch plan with name '{}' does not exist in LaunchManifest!" message = message.format(launch_plan_name) raise LauncherFlowInterruptedException(TAG, message)
def _load_launch_plan_name(): launch_plan_name = ArgLoader.get_arg_loaded_by(ArgLoader.LAUNCH_PLAN_PREFIX) if launch_plan_name is None: message = "No launch plan selected. Launcher will quit." raise LauncherFlowInterruptedException(TAG, message) else: Printer.system_message(TAG, "Selected launch plan: " + Color.GREEN + launch_plan_name + Color.BLUE + ".") return launch_plan_name
def _load_path_set_name(): path_set_name = ArgLoader.get_arg_loaded_by(ArgLoader.PATH_SET_PREFIX) if path_set_name is None: message = "No path set was selected. Launcher will quit." raise LauncherFlowInterruptedException(TAG, message) else: Printer.system_message( TAG, "Selected path set: " + Color.GREEN + path_set_name + Color.BLUE + ".") return path_set_name
def python_check(): if sys.version_info >= MIN_PYTHON_VER: Printer.system_message( "", "Minimum Python version requirement met! Your version: " + Color.GREEN + str(sys.version_info) + Color.BLUE + ".") else: message = ("Invalid Python version. Please use at least Python " + str(MIN_PYTHON_VER[0]) + "." + str(MIN_PYTHON_VER[1]) + ".") raise LauncherFlowInterruptedException("", message)
def _load_path_set(path_manifest, path_set_name): if path_manifest.contains_set(path_set_name): Printer.system_message( TAG, "Path set " + Color.GREEN + path_set_name + Color.BLUE + " was found in PathManifest.") return path_manifest.get_set(path_set_name) else: message = "Invalid path set with name '{}' does not exist in PathManifest!" message = message.format(path_set_name) raise LauncherFlowInterruptedException(TAG, message)
def create_dir(directory): dir_path = clean_path(directory) try: os.makedirs(directory) except Exception as e: message = "Unable to create directory '{}'. Error message: {}" message = message.format(dir_path, str(e)) raise LauncherFlowInterruptedException(TAG, message) return True
def _load_test_set_name(): test_set_names = ArgLoader.get_arg_loaded_by(ArgLoader.TEST_SET_PREFIX) if test_set_names is None or len(test_set_names) == 0: message = "No test set inserted. Launcher will quit." raise LauncherFlowInterruptedException(TAG, message) else: Printer.system_message(TAG, "Selected test sets: ") for t_set_name in test_set_names: Printer.system_message( TAG, " * " + Color.GREEN + t_set_name + Color.BLUE) return test_set_names
def _load_launch_plan_manifest(): launch_manifest_dir = make_path_absolute(ArgLoader.get_manifest_dir(ArgLoader.LAUNCH_MANIFEST_DIR_KEY)) if launch_manifest_dir is None: message = ("LaunchManifest file directory was not found. Check if config_files_dir.json exists in root " "of project. Otherwise check if it's linking to existing file.") raise LauncherFlowInterruptedException(TAG, message) else: launch_manifest = LaunchManifest(launch_manifest_dir) Printer.system_message(TAG, "Created LaunchManifest from file: " + Color.GREEN + launch_manifest_dir + Color.BLUE + ".") return launch_manifest
def _load_avd_manifest(): avd_manifest_dir = make_path_absolute(ArgLoader.get_manifest_dir(ArgLoader.AVD_MANIFEST_DIR_KEY)) if avd_manifest_dir is None: message = ("AvdManifest file directory was not found. Check if config_files_dir.json exists in root of" + "project. Otherwise check if it's linking to existing file.") raise LauncherFlowInterruptedException(TAG, message) else: avd_manifest = AvdManifest(avd_manifest_dir) Printer.system_message(TAG, "Created AvdManifest from file: " + Color.GREEN + avd_manifest_dir + Color.BLUE + ".") return avd_manifest
def _load_avd_schema(avd_manifest, avd_set, avd_set_name): avd_schema_dict = avd_manifest.avd_schema_dict for avd in avd_set.avd_list: if avd_manifest.contains_schema(avd.avd_name): Printer.system_message(TAG, "AVD schema " + Color.GREEN + avd.avd_name + Color.BLUE + " was found in AvdManifest.") else: message = "Set '{}' requests usage of AVD schema with name '{}' which doesn't exists in AVD schema list." message = message.format(avd_set_name, avd.avd_name) raise LauncherFlowInterruptedException(TAG, message) return avd_schema_dict
def create_file(directory, file_name, extension): file_path = clean_path(directory + str(file_name) + "." + extension) try: if not dir_exists(directory): os.makedirs(directory) open(file_path, "w", encoding="utf-8") except Exception as e: message = "Unable to create file '{}.{}'. Error message: {}" message = message.format(file_path, extension, str(e)) raise LauncherFlowInterruptedException(TAG, message) return True
def load_json(json_dir): json_dir = clean_path(json_dir) with open(json_dir, "r", encoding="utf-8") as json_file: json_data = json_file.read() try: json_dict = json.loads(json_data) except Exception as e: message = "Unable to parse JSON file '{}/{}'. Error message: {}" message = message.format(os.getcwd(), json_dir, str(e)) raise LauncherFlowInterruptedException(TAG, message) return json_dict
def clear_dir(directory): if list_files_in_dir(directory): for the_file in list_files_in_dir(directory): file_path = os.path.join(directory, the_file) try: if file_exists(file_path): os.unlink(file_path) elif file_exists(file_path): shutil.rmtree(file_path) except Exception as e: message = "Unable to delete files in directory '{}'. Error message: {}" message = message.format(directory, str(e)) raise LauncherFlowInterruptedException(TAG, message) return True
def _get_apk_package(self): dump = ShellHelper.execute_shell(self.dump_badging_cmd, False, False) regex_result = re.findall("package: name='(.+?)'", dump) if regex_result: package = str(regex_result[0]) if ".test" in package: GlobalConfig.APP_TEST_PACKAGE = package else: GlobalConfig.APP_PACKAGE = package Printer.system_message(self.TAG, "Package that is about to be installed: " + Color.GREEN + package + Color.BLUE + ".") else: message = "Unable to find package of .*apk file: " + self.apk_name raise LauncherFlowInterruptedException(self.TAG, message) return package
def _load_avd_set(avd_manifest, avd_set_name): if avd_manifest.contains_set(avd_set_name): Printer.system_message(TAG, "AVD set " + Color.GREEN + avd_set_name + Color.BLUE + " was found in AvdManifest.") avd_set = avd_manifest.get_set(avd_set_name) Printer.system_message(TAG, "Requested AVD in set:") for requested_avd_schema in avd_set.avd_list: Printer.system_message(TAG, " * " + Color.GREEN + requested_avd_schema.avd_name + Color.BLUE + " - instances num: " + Color.GREEN + str(requested_avd_schema.instances) + Color.BLUE + ".") else: message = "Invalid AVD set. Set '{}' does not exist in AvdManifest!" message = message.format(avd_set_name) raise LauncherFlowInterruptedException(TAG, message) return avd_manifest.get_set(avd_set_name)
def get_existing_apk(self, test_set): apk_candidate = self.apk_store.usable_apk_candidate if apk_candidate is None: apk_candidate = self.apk_store.provide_apk(test_set) if apk_candidate is None: message = "No .apk* candidates for test session were found. Check your config. Launcher will quit." raise LauncherFlowInterruptedException(self.TAG, message) session_logger.log_app_apk(apk_candidate.apk_name) session_logger.log_test_apk(apk_candidate.test_apk_name) session_logger.log_apk_version_code(apk_candidate.apk_version) if session_logger.session_log.apk_summary.apk_build_time is None: session_logger.session_log.apk_summary.apk_build_time = 0 if session_logger.session_log.apk_summary.test_apk_build_time is None: session_logger.session_log.apk_summary.test_apk_build_time = 0 return apk_candidate
def _check_port_rules(avd_set): avd_instances = 0 avd_rules = avd_set.avd_port_rules for avd in avd_set.avd_list: avd_instances += avd.instances if len(avd_rules.ports_to_use) != len(set(avd_rules.ports_to_use)): message = "'Ports to use' list contains duplicates." raise LauncherFlowInterruptedException(TAG, message) if len(avd_rules.ports_to_ignore) != len(set(avd_rules.ports_to_ignore)): message = "'Ports to ignore' list contains duplicates." raise LauncherFlowInterruptedException(TAG, message) for port_to_be_used in avd_rules.ports_to_use: if port_to_be_used % 2 == 1: message = "Port numbers has to be even." raise LauncherFlowInterruptedException(TAG, message) for port_to_be_used in avd_rules.ports_to_use: if port_to_be_used < avd_rules.search_range_min or port_to_be_used > avd_rules.search_range_max: message = "Requested to use port {} is out of range <{}, {}>." message = message.format(str(port_to_be_used), str(avd_rules.search_range_min), str(avd_rules.search_range_max)) raise LauncherFlowInterruptedException(TAG, message) for port_to_be_ignored in avd_rules.ports_to_ignore: for port_to_be_used in avd_rules.ports_to_use: if port_to_be_used == port_to_be_ignored: message = "Port {} is set to be used and ignored at the same time." message = message.format(str(port_to_be_used)) raise LauncherFlowInterruptedException(TAG, message) if not avd_rules.assign_missing_ports: requested_ports_to_use_num = len(avd_rules.ports_to_use) if requested_ports_to_use_num != avd_instances: message = ( "There are {} AVD instances about to be created according to set, but there were only {} ports " "requested to use. Set 'assign_missing_ports' to True or add more ports to list." ) message = message.format(str(avd_instances), str(requested_ports_to_use_num)) raise LauncherFlowInterruptedException(TAG, message)
def _pick_test_set(test_manifest, test_set_names): if len(test_set_names) > 1: Printer.system_message( TAG, "There were " + Color.GREEN + "{}".format(len(test_set_names)) + Color.BLUE + " test sets passed. Merge will occur now.") test_set_dict = dict() test_set_dict["set_name"] = "merged" test_set_dict["apk_name_part"] = None test_set_dict["application_apk_assemble_task"] = None test_set_dict["test_apk_assemble_task"] = None test_set_dict["gradle_build_params"] = None test_set_dict["shard"] = None test_set_dict["set_package_names"] = set() config_compatible = True errors_tuples = set() for test_set_name in test_set_names: test_set = test_manifest.get_set(test_set_name) for other_test_set_name in test_set_names: other_test_set = test_manifest.get_set(other_test_set_name) if test_set.apk_name_part != other_test_set.apk_name_part: config_compatible = False errors_tuples.add( (test_set_name, other_test_set_name, "apk_name_part")) else: test_set_dict["apk_name_part"] = test_set.apk_name_part if test_set.application_apk_assemble_task != other_test_set.application_apk_assemble_task: config_compatible = False errors_tuples.add((test_set_name, other_test_set_name, "application_apk_assemble_task")) else: test_set_dict[ "application_apk_assemble_task"] = test_set.application_apk_assemble_task if test_set.test_apk_assemble_task != other_test_set.test_apk_assemble_task: config_compatible = False errors_tuples.add((test_set_name, other_test_set_name, "test_apk_assemble_task")) else: test_set_dict[ "test_apk_assemble_task"] = test_set.test_apk_assemble_task if test_set.gradle_build_params != other_test_set.gradle_build_params: config_compatible = False errors_tuples.add((test_set_name, other_test_set_name, "gradle_build_params")) else: test_set_dict[ "gradle_build_params"] = test_set.gradle_build_params if test_set.shard != other_test_set.shard: config_compatible = False errors_tuples.add( (test_set_name, other_test_set_name, "shard")) else: test_set_dict["shard"] = test_set.shard for package in test_set.set_package_names: test_set_dict["set_package_names"].add(package) if config_compatible: Printer.system_message( TAG, "All tests sets are compatible and were successfully merged. Including packages:" ) merged_test_set = TestSet(test_set_dict) for package_name in merged_test_set.set_package_names: Printer.system_message( TAG, " * " + Color.GREEN + package_name + Color.BLUE) return merged_test_set else: error = "" for tset1, tset2, parameter_name in errors_tuples: error += "\n - Test set '{}' and test set '{}' have incompatible ".format(tset1, tset2) \ + "config (on parameter: {}) and cannot be merged.".format(parameter_name) raise LauncherFlowInterruptedException(TAG, error) else: return test_manifest.get_set(test_set_names[0])
def get_open_ports(avd_set): _check_port_rules(avd_set) ports_to_use = avd_set.avd_port_rules.ports_to_use if len(ports_to_use) > 0: message = "Requested ports:" for port in ports_to_use: message += (" '" + str(port) + "'") message += "." message(TAG, message) ports_to_ignore = avd_set.avd_port_rules.ports_to_ignore if len(ports_to_ignore) > 0: message = "Ignoring ports:" for port in ports_to_ignore: message += (" '" + str(port) + "'") message += "." Printer.system_message(TAG, message) should_assign_missing_ports = avd_set.avd_port_rules.assign_missing_ports if should_assign_missing_ports: Printer.system_message( TAG, "Not requested ports will be automatically assigned.") else: Printer.system_message( TAG, "Port auto assignment is turned off. Only specified ports will be used." ) avd_instances = 0 for avd in avd_set.avd_list: avd_instances += avd.instances range_min = avd_set.avd_port_rules.search_range_min range_max = avd_set.avd_port_rules.search_range_max Printer.system_message( TAG, "Checking for " + str(avd_instances) + " open ports in range <" + str(range_min) + ", " + str(range_max) + ">.") available_ports = list() for port in ports_to_use: try: ShellHelper.execute_shell(GeneralCommand.CHECK_PORT.format(port), False, False) port_open = False except: port_open = True if port_open: available_ports.append(port) else: message = "Port {} was requested but is currently used." message = message.format(str(port)) raise LauncherFlowInterruptedException(TAG, message) if should_assign_missing_ports: temp_port = range_min for i in range(avd_instances - len(available_ports)): while temp_port < range_max and len( available_ports) != avd_instances: try: ShellHelper.execute_shell( GeneralCommand.CHECK_PORT.format(temp_port), False, False) port_open = False except: port_open = True if port_open: if temp_port not in available_ports and temp_port not in ports_to_ignore: available_ports.append(temp_port) else: Printer.error( TAG, "Port " + str(temp_port) + " is currently used and will be omitted.") temp_port += 2 if len(available_ports) != avd_instances: message = "There are only {} open ports available in range <{}, {}>. Requested amount: {}." message = message.format(str(len(available_ports)), str(range_min), str(range_max), str(avd_instances)) raise LauncherFlowInterruptedException(TAG, message) return available_ports
def _load_test_list(test_manifest): if test_manifest.test_package_list: return test_manifest.test_package_list else: message = "There are no tests specified in TestManifest! Launcher will quit." raise LauncherFlowInterruptedException(TAG, message)
def _load_launch_plan_to_global_settings(launch_plan): avd_set = ArgLoader.get_arg_loaded_by(ArgLoader.AVD_SET_PREFIX) is_avd_session_requested = avd_set is not None and avd_set != ArgLoader.AVD_SET_DEFAULT Printer.system_message(TAG, "General:") general_settings = launch_plan.general if is_avd_session_requested: GlobalConfig.SHOULD_USE_ONLY_DEVICES_SPAWNED_IN_SESSION = True else: GlobalConfig.SHOULD_USE_ONLY_DEVICES_SPAWNED_IN_SESSION = False GlobalConfig.ADB_CALL_BUFFER_SIZE = general_settings.adb_call_buffer_size if GlobalConfig.ADB_CALL_BUFFER_SIZE > 0: Printer.system_message(TAG, " * ADB call buffer size set to: " + Color.GREEN + str(GlobalConfig.ADB_CALL_BUFFER_SIZE) + " slot(s)" + Color.BLUE + ".") else: message = "ADB_CALL_BUFFER_SIZE cannot be smaller than 1. Launcher will quit." raise LauncherFlowInterruptedException(TAG, message) GlobalConfig.ADB_CALL_BUFFER_DELAY_BETWEEN_CMD = general_settings.adb_call_buffer_delay_between_cmd if GlobalConfig.ADB_CALL_BUFFER_DELAY_BETWEEN_CMD >= 0: if GlobalConfig.ADB_CALL_BUFFER_DELAY_BETWEEN_CMD == 0: Printer.system_message(TAG, " * ADB call buffer is disabled. ADB_CALL_BUFFER_DELAY_BETWEEN_CMD" " param set to: " + + Color.GREEN + "0 second(s)" + + Color.BLUE + ".") else: Printer.system_message(TAG, " * ADB call buffer will clear slots after " + Color.GREEN + str(GlobalConfig.ADB_CALL_BUFFER_DELAY_BETWEEN_CMD / 1000) + " second(s)" + Color.BLUE + " from ADB call.") else: message = "ADB_CALL_BUFFER_DELAY_BETWEEN_CMD cannot be negative! Launcher will quit." raise LauncherFlowInterruptedException(TAG, message) if is_avd_session_requested: Printer.system_message(TAG, "Device preparation phase settings:") device_prep_settings = launch_plan.device_preparation_phase GlobalConfig.SHOULD_RECREATE_EXISTING_AVD = device_prep_settings.avd_should_recreate_existing if GlobalConfig.SHOULD_RECREATE_EXISTING_AVD: Printer.system_message(TAG, " * If requested AVD already exists - it will be" + Color.GREEN + " recreated from scratch" + Color.BLUE + ".") else: Printer.system_message(TAG, " * If requested AVD already exists - it will be" + Color.GREEN + " reused" + Color.BLUE + ".") Printer.system_message(TAG, "Device launching phase settings:") device_launch_settings = launch_plan.device_launching_phase GlobalConfig.IGNORED_DEVICE_LIST = device_launch_settings.device_android_id_to_ignore Printer.system_message(TAG, " * Devices with following Android-IDs will be ignored: " + Color.GREEN + str(GlobalConfig.IGNORED_DEVICE_LIST) + Color.BLUE + ".") if is_avd_session_requested: GlobalConfig.SHOULD_LAUNCH_AVD_SEQUENTIALLY = device_launch_settings.avd_launch_sequentially if GlobalConfig.SHOULD_LAUNCH_AVD_SEQUENTIALLY: Printer.system_message(TAG, " * AVD will be launched " + Color.GREEN + "one by one" + Color.BLUE + ". Wait for start will be performed for each AVD separately and it will take more" " time.") else: Printer.system_message(TAG, " * AVD will be launched " + Color.GREEN + "all at once" + Color.BLUE + ".") Printer.error(TAG, "Warning: when launching AVD simultaneously ADB is unaware of the amount of memory" " that specific AVD will use. If there is not enough memory in the system and you launch" " too many AVD at the same time your PC might turn off due to lack of RAM memory.") GlobalConfig.ADB_SCAN_INTERVAL = device_launch_settings.avd_status_scan_interval_millis if GlobalConfig.ADB_SCAN_INTERVAL is "": message = " * ADB_SCAN_INTERVAL not specified in LaunchManifest. Launcher will quit." raise LauncherFlowInterruptedException(TAG, message) else: Printer.system_message(TAG, " * ADB will be scanned with interval of " + Color.GREEN + str(GlobalConfig.ADB_SCAN_INTERVAL / 1000) + " second(s)" + Color.BLUE + ".") GlobalConfig.AVD_ADB_BOOT_TIMEOUT = device_launch_settings.avd_wait_for_adb_boot_timeout_millis if GlobalConfig.AVD_ADB_BOOT_TIMEOUT is "": message = " * AVD_ADB_BOOT_TIMEOUT not specified in LaunchManifest. Launcher will quit." raise LauncherFlowInterruptedException(TAG, message) else: Printer.system_message(TAG, " * AVD - ADB boot timeout set to " + Color.GREEN + str(GlobalConfig.AVD_ADB_BOOT_TIMEOUT / 1000) + " second(s)" + Color.BLUE + ".") GlobalConfig.AVD_SYSTEM_BOOT_TIMEOUT = device_launch_settings.avd_wait_for_system_boot_timeout_millis if GlobalConfig.AVD_SYSTEM_BOOT_TIMEOUT is "": message = " * AVD_SYSTEM_BOOT_TIMEOUT not specified in LaunchManifest. Launcher will quit." raise LauncherFlowInterruptedException(TAG, message) else: Printer.system_message(TAG, " * AVD - ADB system boot timeout set to " + Color.GREEN + str(GlobalConfig.AVD_SYSTEM_BOOT_TIMEOUT / 1000) + " second(s)" + Color.BLUE + ".") GlobalConfig.SHOULD_RESTART_ADB = device_launch_settings.device_before_launching_restart_adb if GlobalConfig.SHOULD_RESTART_ADB: Printer.system_message(TAG, " * " + Color.GREEN + "ADB will be restarted" + Color.BLUE + " before launching tests.") Printer.system_message(TAG, "Apk preparation phase settings:") apk_preparation_settings = launch_plan.apk_preparation_phase GlobalConfig.SHOULD_BUILD_NEW_APK = apk_preparation_settings.build_new_apk if GlobalConfig.SHOULD_BUILD_NEW_APK: Printer.system_message(TAG, " * Launcher will " + Color.GREEN + "build .*apk" + Color.BLUE + " for tests with commands specified in test set.") else: Printer.system_message(TAG, " * Launcher will " + Color.GREEN + "look for existing .*apk" + Color.BLUE + " look for existing .*apk for tests and try to build only if nothing was found.") Printer.system_message(TAG, "Test run phase settings:") testing_phase = launch_plan.testing_phase GlobalConfig.SHOULD_RECORD_TESTS = testing_phase.record_tests if GlobalConfig.SHOULD_RECORD_TESTS: Printer.system_message(TAG, " * Launcher will " + Color.GREEN + "record device screens" + Color.BLUE + " during test session.") else: Printer.system_message(TAG, " * Launcher test " + Color.GREEN + "recording is turned off" + Color.BLUE + ".") Printer.system_message(TAG, "Flakiness check phase settings:") flakiness_check_phase = launch_plan.flakiness_check_phase GlobalConfig.SHOULD_RERUN_FAILED_TESTS = flakiness_check_phase.should_rerun_failed_tests GlobalConfig.FLAKINESS_RERUN_COUNT = flakiness_check_phase.rerun_count if GlobalConfig.SHOULD_RERUN_FAILED_TESTS: Printer.system_message(TAG, " * Launcher will " + Color.GREEN + "re-run failed tests {} times".format( GlobalConfig.FLAKINESS_RERUN_COUNT) + Color.BLUE + " after test session ends.") else: Printer.system_message(TAG, " * Launcher test " + Color.GREEN + "re-running option is turned off" + Color.BLUE + ".")
def _run_tests(self, devices, test_cmd_templates, is_rerunning=False): device_commands_dict = self._prepare_device_control_cmds(devices) threads_finished = False logcat_threads_num = len(devices) recording_threads_num = len( devices) if GlobalConfig.SHOULD_RECORD_TESTS else 0 test_threads_num = len(test_cmd_templates) logcat_threads = list() test_threads = list() test_log_saving_threads = list() logcat_saving_threads = list() test_recording_saving_threads = list() try: while not threads_finished: if len(logcat_threads) != logcat_threads_num: for device in devices: logcat_thread = TestLogCatMonitorThread( device, device_commands_dict.get(device), GlobalConfig.SHOULD_RECORD_TESTS) logcat_threads.append(logcat_thread) logcat_thread.start() if len(test_recording_saving_threads) != recording_threads_num: for device in devices: test_recording_saving_thread = TestRecordingSavingThread( device) test_recording_saving_threads.append( test_recording_saving_thread) test_recording_saving_thread.start() if len(test_threads) != test_threads_num and all( t.logcat_process is not None for t in logcat_threads): for device in devices: if not any(t.device.adb_name == device.adb_name and t.is_alive() for t in test_threads) \ and len(test_cmd_templates) > 0: launch_cmd_template = test_cmd_templates.pop(0) launch_cmd = launch_cmd_template.replace( self.DEVICE_NAME_PLACEHOLDER, device.adb_name) instance = "packages" if not is_rerunning else "tests" Printer.system_message( self.TAG, str(len(test_cmd_templates)) + " {} to run left...".format(instance)) self.adb_package_manager_controller.clear_package_cache( device.adb_name, GlobalConfig.APP_PACKAGE) test_thread = TestThread(launch_cmd, device) test_threads.append(test_thread) test_thread.start() for test_thread in test_threads: if len(test_thread.logs) > 0: current_test_logs = copy.deepcopy(test_thread.logs) self.test_store.store_test_status(current_test_logs) for test_log in current_test_logs: contain_count = self.test_store.test_contain_count( test_log.test_name) if contain_count > 1: test_log.rerun_count += contain_count - 1 if is_rerunning: session_logger.update_flaky_candidate(test_log) else: if test_log.test_status == "success": session_logger.increment_passed_tests() if test_log.test_status == "failure": session_logger.increment_failed_tests() test_log_saving_thread = TestSummarySavingThread( test_thread.device, current_test_logs) test_log_saving_threads.append(test_log_saving_thread) test_log_saving_thread.start() test_thread.logs.clear() for logcat_thread in logcat_threads: if len(logcat_thread.logs) > 0: current_logcats = copy.deepcopy(logcat_thread.logs) self.test_store.store_test_logcat(current_logcats) for test_logcat in current_logcats: contain_count = self.test_store.test_logcat_contain_count( test_logcat.test_name) if contain_count > 1: test_logcat.rerun_count += contain_count - 1 logcat_saving_thread = TestLogcatSavingThread( logcat_thread.device, current_logcats) logcat_saving_threads.append(logcat_saving_thread) logcat_saving_thread.start() logcat_thread.logs.clear() if len(logcat_thread.recordings) > 0: device = logcat_thread.device current_recordings = copy.deepcopy( logcat_thread.recordings) for recording_saving_thread in test_recording_saving_threads: if recording_saving_thread.device.adb_name == device.adb_name: pull_cmd_list = list() clear_cmd_list = list() for recording_name in current_recordings: recording_dir = FileUtils.add_ending_slash( FileUtils.clean_path( GlobalConfig. DEVICE_VIDEO_STORAGE_DIR) ) + recording_name pull_cmd_list.append( self._prepare_pull_recording_cmd( device, recording_dir)) clear_cmd_list.append( self._prepare_remove_recording_cmd( device, recording_dir)) recording_saving_thread.add_recordings( current_recordings) recording_saving_thread.add_pull_recording_cmds( pull_cmd_list) recording_saving_thread.add_clear_recordings_cmd( clear_cmd_list) logcat_thread.recordings.clear() if len(test_threads) == test_threads_num \ and all(not t.is_alive() for t in test_threads) \ and all(t.is_finished() for t in test_log_saving_threads) \ and all(t.is_finished() for t in logcat_saving_threads): for test_thread in test_threads: test_thread.kill_processes() test_thread.join() for logcat_thread in logcat_threads: logcat_thread.kill_processes() logcat_thread.join() for test_log_saving_thread in test_log_saving_threads: test_log_saving_thread.join() for logcat_saving_thread in logcat_saving_threads: logcat_saving_thread.join() test_threads.clear() logcat_threads.clear() test_log_saving_threads.clear() logcat_saving_threads.clear() if len(test_recording_saving_threads) > 0 and len( logcat_threads) == 0: if all( len(t.recordings) == 0 for t in test_recording_saving_threads): for recording_thread in test_recording_saving_threads: recording_thread.kill_processes() recording_thread.join() test_recording_saving_threads.clear() threads_finished = len(logcat_threads) == 0 and len( test_threads) == 0 and len( test_log_saving_threads) == 0 and len( logcat_saving_threads) == 0 and len( test_recording_saving_threads) == 0 and len( test_cmd_templates) == 0 except Exception as e: message = "Error has occurred during test session: \n" + str(e) raise LauncherFlowInterruptedException(self.TAG, message) finally: if len(test_threads) > 0: for test_thread in test_threads: test_thread.kill_processes() test_thread.join() if len(logcat_threads) > 0: for logcat_thread in logcat_threads: logcat_thread.kill_processes() logcat_thread.join() if len(test_log_saving_threads) > 0: for test_log_saving_thread in test_log_saving_threads: test_log_saving_thread.join() if len(logcat_saving_threads) > 0: for logcat_saving_thread in logcat_saving_threads: logcat_saving_thread.join() if len(test_recording_saving_threads) > 0: for recording_thread in test_recording_saving_threads: recording_thread.kill_processes() recording_thread.join() test_threads.clear() logcat_threads.clear() test_log_saving_threads.clear() logcat_saving_threads.clear() test_recording_saving_threads.clear()
def _wait_for_property_statuses(self, monitored_devices): Printer.system_message( self.TAG, "Waiting for 'dev.bootcomplete', 'sys.boot_completed', 'init.svc.bootanim', " "properties of devices (" + " ".join("'" + device.adb_name + "'" for device in monitored_devices) + ").") device_statuses = dict() for device in monitored_devices: device_statuses.update({device.adb_name: None}) start_time = last_scan_ended = time.time() * 1000 while True: current_time = time.time() * 1000 if current_time - last_scan_ended >= GlobalConfig.ADB_SCAN_INTERVAL or start_time == last_scan_ended: Printer.system_message(self.TAG, "Scanning...") for device in self.device_store.get_devices(): if device in monitored_devices: dev_boot = (self.adb_shell_controller.get_property( device.adb_name, "dev.bootcomplete")).strip() sys_boot = (self.adb_shell_controller.get_property( device.adb_name, "sys.boot_completed")).strip() boot_anim = (self.adb_shell_controller.get_property( device.adb_name, "init.svc.bootanim")).strip() boot_finished = dev_boot == "1" and sys_boot == "1" and boot_anim == "stopped" device_statuses.update({ device.adb_name: { "dev.bootcomplete": dev_boot, "sys.boot_completed": sys_boot, "init.svc.bootanim": boot_anim, "boot_finished": boot_finished } }) if boot_finished: session_logger.log_device_launch_end_time( device.adb_name) Printer.system_message(self.TAG, " * Current wait status:") for device_name, status_dict in device_statuses.items(): bcplte = str( status_dict["dev.bootcomplete"] if status_dict["dev.bootcomplete"] != "" else "0") bcplted = str( status_dict["sys.boot_completed"] if status_dict["sys.boot_completed"] != "" else "0") banim = str(status_dict["init.svc.bootanim"]) launched_status = "launched" if status_dict[ "boot_finished"] else "not-launched" Printer.system_message( self.TAG, " " + device_name + " properties: " + "('dev.bootcomplete' : " + bcplte + ", " + "'sys.boot_completed' : " + bcplted + ", " + "'init.svc.bootanim' : " + banim + ") - " + Color.GREEN + launched_status + Color.BLUE) if all(status_dict["boot_finished"] for status_dict in device_statuses.values()): break last_scan_ended = time.time() * 1000 if current_time - start_time >= GlobalConfig.AVD_SYSTEM_BOOT_TIMEOUT: message = "Devices took longer than seconds to launch (Property launch). Timeout quit." message = message.format( str(GlobalConfig.AVD_SYSTEM_BOOT_TIMEOUT)) raise LauncherFlowInterruptedException(self.TAG, message) Printer.system_message(self.TAG, "Property launch finished with success!")
def _install_apk(self, apk): aapt_cmd_assembler = self.aapt_controller.aapt_command_assembler app_apk_log_note = "appApkThread" test_apk_log_note = "testApkThread" for device in self.device_store.get_devices(): if device.status != "device": message = (".*apk won't be installed on device with name " + device.adb_name + " because it's ADB " + "status is set to " + device.status + " instead of 'device'.") raise LauncherFlowInterruptedException(self.TAG, message) apk_install_threads = dict() for device in self.device_store.get_devices(): app_dump_badging_cmd = aapt_cmd_assembler.assemble_dump_badging_cmd( self.aapt_controller.aapt_bin, apk.apk_path) app_apk_thread = ApkInstallThread(app_dump_badging_cmd, device, apk.apk_name, apk.apk_path) app_apk_thread.note = app_apk_log_note test_dump_badging_cmd = aapt_cmd_assembler.assemble_dump_badging_cmd( self.aapt_controller.aapt_bin, apk.test_apk_path) test_apk_thread = ApkInstallThread(test_dump_badging_cmd, device, apk.test_apk_name, apk.test_apk_path) test_apk_thread.note = test_apk_log_note thread_list = list() thread_list.append(app_apk_thread) thread_list.append(test_apk_thread) apk_install_threads.update({device: thread_list}) all_devices_have_apk_installed = False while not all_devices_have_apk_installed: for device in self.device_store.get_devices(): device_threads = apk_install_threads[device] for thread in device_threads: if any(thread.is_alive() for thread in device_threads): break if not thread.is_finished: thread.start() if thread.note == app_apk_log_note: session_logger.log_app_apk_install_start_time_on_device( device.adb_name) if thread.note == test_apk_log_note: session_logger.log_test_apk_install_start_time_on_device( device.adb_name) all_threads_has_finished = True for device in self.device_store.get_devices(): device_threads = apk_install_threads[device] for thread in device_threads: if thread.is_finished: if thread.note == app_apk_log_note: session_logger.log_app_apk_install_end_time_on_device( device.adb_name) if thread.note == test_apk_log_note: session_logger.log_test_apk_install_end_time_on_device( device.adb_name) else: all_threads_has_finished = False if not all_threads_has_finished: break all_devices_have_apk_installed = all_threads_has_finished