예제 #1
0
    def _init_phase():
        Printer.phase("INIT")
        session_logger.log_session_start_time()

        Printer.step("Launcher started working!")
        Version.info()
        Version.python_check()
예제 #2
0
    def _testing_phase(self):
        Printer.phase("TESTING")
        session_logger.log_total_test_start_time()

        Printer.step("Starting tests.")
        self.test_manager.run_tests(self.test_set, self.test_list)

        session_logger.log_total_test_end_time()
예제 #3
0
    def _flakiness_check_phase(self):
        if GlobalConfig.SHOULD_RERUN_FAILED_TESTS:
            Printer.phase("FLAKINESS CHECK")
            session_logger.log_total_rerun_start_time()

            Printer.step("Re-running failed tests.")
            self.test_manager.rerun_failed_tests()

            session_logger.log_total_rerun_end_time()
예제 #4
0
    def _apk_installation_phase(self):
        Printer.phase("APK INSTALLATION")
        session_logger.log_total_apk_install_start_time()

        Printer.step("Installing .*apk on devices included in test session.")
        apk = self.apk_manager.get_existing_apk(self.test_set)
        self.apk_manager.install_apk_on_devices(apk)

        session_logger.log_total_apk_install_end_time()
예제 #5
0
    def launch_all_avd_sequentially(self):
        for device in self.device_store.get_devices():
            if isinstance(
                    device,
                    SessionVirtualDevice) and device.status == "not-launched":
                session_logger.log_device_launch_start_time(device.adb_name)
                device.launch()

            self._wait_for_adb_statuses_change_to("device", (device, ))
        self._wait_for_property_statuses(self.device_store.get_devices())
예제 #6
0
    def _device_launch_phase(self):
        Printer.phase("DEVICE LAUNCH")
        session_logger.log_total_device_launch_start_time()

        if GlobalConfig.SHOULD_USE_ONLY_DEVICES_SPAWNED_IN_SESSION:
            if GlobalConfig.SHOULD_LAUNCH_AVD_SEQUENTIALLY:
                Printer.step("Launching AVD - sequentially.")
                self.device_manager.launch_all_avd_sequentially()
            else:
                Printer.step("Launching AVD - all at once.")
                self.device_manager.launch_all_avd_at_once()
        else:
            Printer.step("Using currently launched devices.")

        session_logger.log_total_device_launch_end_time()
예제 #7
0
    def _device_preparation_phase(self):
        Printer.phase("DEVICE PREPARATION")

        if GlobalConfig.SHOULD_USE_ONLY_DEVICES_SPAWNED_IN_SESSION:
            Printer.step("Killing currently launched AVD.")
            session_logger.log_total_device_creation_start_time()

            self.device_manager.add_models_representing_outside_session_virtual_devices(
            )
            if self.device_manager.is_any_avd_visible():
                self.device_manager.kill_all_avd()
            self.device_manager.clear_models_representing_outside_session_virtual_devices(
            )

            if self.avd_set.avd_list:
                Printer.step(
                    "Creating models for devices specified in AVD set.")
                self.device_manager.add_models_based_on_avd_schema(
                    self.avd_set, self.avd_schemas)

                if GlobalConfig.SHOULD_RECREATE_EXISTING_AVD:
                    Printer.step(
                        "Creating all requested AVD from scratch. Recreating existing ones."
                    )
                    self.device_manager.create_all_avd_and_recreate_existing()
                else:
                    Printer.step(
                        "Creating all requested AVD from scratch. Reusing existing ones."
                    )
                    self.device_manager.create_all_avd_and_reuse_existing()

            session_logger.log_total_device_creation_end_time()
        else:
            Printer.step(
                "Creating models for currently visible Android Devices and AVD."
            )
            self.device_manager.add_models_representing_outside_session_devices(
            )
            self.device_manager.add_models_representing_outside_session_virtual_devices(
            )

        if not self.device_manager.is_any_avd_visible():
            quit()

        if GlobalConfig.IGNORED_DEVICE_LIST:
            Printer.step("Checking device ignore list")
            self.device_manager.clear_models_with_android_ids_in_ignore_list()
예제 #8
0
    def _apk_preparation_phase(self):
        Printer.phase("APK PREPARATION")
        session_logger.log_total_apk_build_start_time()

        Printer.step("Preparing .*apk for test.")
        if GlobalConfig.SHOULD_BUILD_NEW_APK:
            apk = self.apk_manager.build_apk(self.test_set)
        else:
            apk = self.apk_manager.get_existing_apk(self.test_set)
            if apk is None:
                apk = self.apk_manager.build_apk(self.test_set)
        self.apk_manager.display_picked_apk_info()

        Printer.step("Scanning .*apk for helpful data.")
        self.apk_manager.set_instrumentation_runner_according_to(apk)

        session_logger.log_total_apk_build_end_time()
예제 #9
0
    def create_all_avd_and_recreate_existing(self):
        created_avd_list = re.findall("Name: (.+)",
                                      self.avdmanager_controller.list_avd())

        for device in self.device_store.get_devices():
            if isinstance(device, SessionVirtualDevice):

                session_logger.log_device_creation_start_time(device.adb_name)
                start_time = int(round(time.time() * 1000))
                if device.avd_schema.avd_name in created_avd_list:
                    Printer.system_message(
                        self.TAG, "AVD with name " + Color.GREEN +
                        device.avd_schema.avd_name + Color.BLUE +
                        " already exists and will be re-created.")
                    device.delete()
                    device.create()
                else:
                    device.create()

                if device.avd_schema.create_avd_hardware_config_filepath != "":
                    Printer.system_message(
                        self.TAG,
                        "'config.ini' file was specified in AVD schema of device "
                        + Color.GREEN + device.adb_name + Color.BLUE +
                        " in location " + Color.GREEN +
                        device.avd_schema.create_avd_hardware_config_filepath +
                        Color.BLUE + ". Applying...")
                    device.apply_config_ini()
                end_time = int(round(time.time() * 1000))
                session_logger.log_device_creation_end_time(device.adb_name)

                creation_time = (end_time - start_time) / 1000
                reasonable_time = 25
                if creation_time > reasonable_time and "--force" not in device.avd_schema.create_avd_additional_options:
                    Printer.system_message(
                        self.TAG, "AVD creation took: " + Color.GREEN +
                        str(creation_time) + " sec" + Color.RED +
                        " (Attention! Creation process could ran faster. Try adding "
                        +
                        "'--force' to your AVD schema in 'create_avd_additional_options' field.)"
                    )
                else:
                    Printer.system_message(
                        self.TAG, "AVD creation took: " + Color.GREEN +
                        str(creation_time) + Color.BLUE + " sec")
예제 #10
0
    def build_apk(self, test_set):
        Printer.system_message(
            self.TAG, "Building application and test .*apk from scratch.")

        session_logger.log_app_apk_build_start_time()
        self.gradle_controller.build_application_apk(test_set)
        session_logger.log_app_apk_build_end_time()

        session_logger.log_test_apk_build_start_time()
        self.gradle_controller.build_test_apk(test_set)
        session_logger.log_test_apk_build_end_time()

        return self.get_existing_apk(test_set)
예제 #11
0
    def _finalization_phase(self):
        Printer.phase("FINALIZATION")

        Printer.step("Displaying saved files during test session.")
        session_logger.dump_saved_files_history()

        Printer.step("Session summary.")
        session_logger.log_session_end_time()
        session_logger.save_session_summary()
        session_logger.dump_session_summary()
        LogGenerator.generate_logs(self.test_set)

        if self.device_manager is not None and self.device_manager.is_any_avd_visible() \
                and GlobalConfig.SHOULD_USE_ONLY_DEVICES_SPAWNED_IN_SESSION:
            Printer.step("Killing AVD spawned for test session.")
            self.device_manager.kill_all_avd()
            self.device_manager.clear_models_based_on_avd_schema()
예제 #12
0
    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
예제 #13
0
    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()
예제 #14
0
    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
예제 #15
0
    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!")
예제 #16
0
    def run_tests(self, test_set, test_list):
        devices = self.device_store.get_devices()
        test_packages = self.test_store.get_packages(test_set, test_list)

        launch_variant_string = "TESTS SPLIT INTO SHARDS" if test_set.shard else "EACH TEST ON EACH DEVICE"
        Printer.system_message(
            self.TAG,
            "According to test set settings, tests will be run with following variant: "
            + Color.GREEN + launch_variant_string + Color.BLUE + ".")

        device_commands_dict = self._prepare_device_control_cmds(devices)
        test_cmd_templates = self._prepare_launch_test_cmds_for_run(
            test_packages, devices, test_set.shard)

        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)

                            Printer.system_message(
                                self.TAG,
                                str(len(test_cmd_templates)) +
                                " packages to run left...")

                            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)

                        for log in current_test_logs:
                            if log.test_status == "success":
                                session_logger.increment_passed_tests()

                            if 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)
                        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()