176e6818aSopenharmony_ci#!/usr/bin/env python3
276e6818aSopenharmony_ci# coding=utf-8
376e6818aSopenharmony_ci
476e6818aSopenharmony_ci#
576e6818aSopenharmony_ci# Copyright (c) 2022 Huawei Device Co., Ltd.
676e6818aSopenharmony_ci# Licensed under the Apache License, Version 2.0 (the "License");
776e6818aSopenharmony_ci# you may not use this file except in compliance with the License.
876e6818aSopenharmony_ci# You may obtain a copy of the License at
976e6818aSopenharmony_ci#
1076e6818aSopenharmony_ci#     http://www.apache.org/licenses/LICENSE-2.0
1176e6818aSopenharmony_ci#
1276e6818aSopenharmony_ci# Unless required by applicable law or agreed to in writing, software
1376e6818aSopenharmony_ci# distributed under the License is distributed on an "AS IS" BASIS,
1476e6818aSopenharmony_ci# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1576e6818aSopenharmony_ci# See the License for the specific language governing permissions and
1676e6818aSopenharmony_ci# limitations under the License.
1776e6818aSopenharmony_ci#
1876e6818aSopenharmony_ci
1976e6818aSopenharmony_ciimport copy
2076e6818aSopenharmony_ciimport os
2176e6818aSopenharmony_ciimport sys
2276e6818aSopenharmony_ciimport traceback
2376e6818aSopenharmony_cifrom typing import Union
2476e6818aSopenharmony_ci
2576e6818aSopenharmony_cifrom xdevice import calculate_elapsed_time
2676e6818aSopenharmony_cifrom xdevice import check_result_report
2776e6818aSopenharmony_cifrom xdevice import StateRecorder
2876e6818aSopenharmony_cifrom xdevice import LifeCycle
2976e6818aSopenharmony_cifrom xdevice import ResultCode
3076e6818aSopenharmony_cifrom xdevice import get_cst_time
3176e6818aSopenharmony_cifrom xdevice import platform_logger
3276e6818aSopenharmony_cifrom xdevice import EnvPool
3376e6818aSopenharmony_cifrom xdevice import CaseEnd
3476e6818aSopenharmony_cifrom xdevice import Binder
3576e6818aSopenharmony_ci
3676e6818aSopenharmony_cifrom devicetest.runner.prepare import PrepareHandler
3776e6818aSopenharmony_cifrom devicetest.core.constants import RunResult
3876e6818aSopenharmony_cifrom devicetest.utils.util import clean_sys_resource
3976e6818aSopenharmony_cifrom devicetest.utils.util import get_base_name
4076e6818aSopenharmony_cifrom devicetest.utils.util import get_dir_path
4176e6818aSopenharmony_cifrom devicetest.utils.util import import_from_file
4276e6818aSopenharmony_cifrom devicetest.core.variables import DeccVariable
4376e6818aSopenharmony_cifrom devicetest.core.variables import ProjectVariables
4476e6818aSopenharmony_cifrom devicetest.core.variables import CurCase
4576e6818aSopenharmony_cifrom devicetest.core.exception import DeviceTestError
4676e6818aSopenharmony_cifrom devicetest.core.test_case import DeviceRoot
4776e6818aSopenharmony_cifrom devicetest.core.test_case import BaseCase
4876e6818aSopenharmony_cifrom devicetest.error import ErrorMessage
4976e6818aSopenharmony_cifrom devicetest.log.logger import DeviceTestLog as Log
5076e6818aSopenharmony_cifrom devicetest.report.generation import add_log_caching_handler
5176e6818aSopenharmony_cifrom devicetest.report.generation import del_log_caching_handler
5276e6818aSopenharmony_cifrom devicetest.report.generation import get_caching_logs
5376e6818aSopenharmony_cifrom devicetest.report.generation import generate_report
5476e6818aSopenharmony_ci
5576e6818aSopenharmony_ci
5676e6818aSopenharmony_ciclass RunnerMode:
5776e6818aSopenharmony_ci    PIPELINE = "pipeline"
5876e6818aSopenharmony_ci    DEBUG = "debug"
5976e6818aSopenharmony_ci
6076e6818aSopenharmony_ci
6176e6818aSopenharmony_ciclass TestRunner:
6276e6818aSopenharmony_ci    """executes test cases and
6376e6818aSopenharmony_ci    """
6476e6818aSopenharmony_ci
6576e6818aSopenharmony_ci    def __init__(self):
6676e6818aSopenharmony_ci        self.run_mode = RunnerMode.PIPELINE
6776e6818aSopenharmony_ci        self.run_list = None
6876e6818aSopenharmony_ci        self.no_run_list = None
6976e6818aSopenharmony_ci        self.running = None
7076e6818aSopenharmony_ci        self.configs = None
7176e6818aSopenharmony_ci        self.devices = None
7276e6818aSopenharmony_ci        self.log = Log
7376e6818aSopenharmony_ci        self.start_time = None
7476e6818aSopenharmony_ci        self.test_results = None
7576e6818aSopenharmony_ci        self.upload_result_handler = None
7676e6818aSopenharmony_ci        self.project = None
7776e6818aSopenharmony_ci        self.prepare = None
7876e6818aSopenharmony_ci        self.cur_case = None
7976e6818aSopenharmony_ci        self._repeat = 1
8076e6818aSopenharmony_ci        self._repeat_round = 1
8176e6818aSopenharmony_ci
8276e6818aSopenharmony_ci    def init_pipeline_runner(self, run_list, configs, devices, upload_result_handler):
8376e6818aSopenharmony_ci        self.run_list = run_list
8476e6818aSopenharmony_ci        self.no_run_list = copy.copy(self.run_list)
8576e6818aSopenharmony_ci        self.running = False
8676e6818aSopenharmony_ci        self.configs = configs
8776e6818aSopenharmony_ci        self.devices = devices
8876e6818aSopenharmony_ci        self.start_time = get_cst_time()
8976e6818aSopenharmony_ci        self.test_results = []
9076e6818aSopenharmony_ci        self.upload_result_handler = upload_result_handler
9176e6818aSopenharmony_ci        self.project = ProjectVariables(self.log)
9276e6818aSopenharmony_ci        self.prepare = None
9376e6818aSopenharmony_ci        self.__init_project_variables()
9476e6818aSopenharmony_ci        self.run_mode = RunnerMode.PIPELINE
9576e6818aSopenharmony_ci        self._repeat = self.configs.get("request").config.repeat
9676e6818aSopenharmony_ci        self._repeat_round = self.configs.get("request").get_repeat_round()
9776e6818aSopenharmony_ci
9876e6818aSopenharmony_ci    def init_case_runner(self, run_list: Union[BaseCase, list]):
9976e6818aSopenharmony_ci        # simple case runner
10076e6818aSopenharmony_ci        self.run_list = run_list
10176e6818aSopenharmony_ci        self.run_mode = RunnerMode.DEBUG
10276e6818aSopenharmony_ci        self.log = platform_logger("TestRunner")
10376e6818aSopenharmony_ci
10476e6818aSopenharmony_ci    def __init_project_variables(self):
10576e6818aSopenharmony_ci        """
10676e6818aSopenharmony_ci        testargs:为xDevice透传过来的数据,用户调用CONFIG可获取
10776e6818aSopenharmony_ci        :return:
10876e6818aSopenharmony_ci        """
10976e6818aSopenharmony_ci        self.log.debug("configs:{}".format(self.configs))
11076e6818aSopenharmony_ci        testcases_path = self.configs.get('testcases_path', "")
11176e6818aSopenharmony_ci        testargs = self.configs.get("testargs", {})
11276e6818aSopenharmony_ci        self.__flash_run_list(testargs)
11376e6818aSopenharmony_ci
11476e6818aSopenharmony_ci        self.cur_case = CurCase(self.log)
11576e6818aSopenharmony_ci        self.project.set_project_path()
11676e6818aSopenharmony_ci        self.project.set_testcase_path(testcases_path)
11776e6818aSopenharmony_ci        self.project.set_task_report_dir(self.configs.get("report_path"))
11876e6818aSopenharmony_ci        self.project.set_resource_path(self.get_local_resource_path())
11976e6818aSopenharmony_ci
12076e6818aSopenharmony_ci    def get_local_resource_path(self):
12176e6818aSopenharmony_ci        local_resource_path = os.path.join(
12276e6818aSopenharmony_ci            self.project.project_path, "testcases", "DeviceTest", "resource")
12376e6818aSopenharmony_ci        return local_resource_path
12476e6818aSopenharmony_ci
12576e6818aSopenharmony_ci    def get_local_aw_path(self):
12676e6818aSopenharmony_ci        local_aw_path = os.path.join(
12776e6818aSopenharmony_ci            self.project.project_path, "testcases", "DeviceTest", "aw")
12876e6818aSopenharmony_ci        return local_aw_path
12976e6818aSopenharmony_ci
13076e6818aSopenharmony_ci    def __flash_run_list(self, testargs):
13176e6818aSopenharmony_ci        """
13276e6818aSopenharmony_ci        retry 场景更新run list
13376e6818aSopenharmony_ci        :param testargs:
13476e6818aSopenharmony_ci        :return:
13576e6818aSopenharmony_ci        """
13676e6818aSopenharmony_ci        get_test = testargs.get("test")
13776e6818aSopenharmony_ci        self.log.info("get test:{}".format(get_test))
13876e6818aSopenharmony_ci        retry_test_list = self.parse_retry_test_list(get_test)
13976e6818aSopenharmony_ci        if retry_test_list is not None:
14076e6818aSopenharmony_ci            self.run_list = retry_test_list
14176e6818aSopenharmony_ci            self.no_run_list = copy.copy(self.run_list)
14276e6818aSopenharmony_ci            self.log.info("retry test list:{}".format(retry_test_list))
14376e6818aSopenharmony_ci
14476e6818aSopenharmony_ci    def parse_retry_test_list(self, retry_test_list):
14576e6818aSopenharmony_ci        if retry_test_list is None:
14676e6818aSopenharmony_ci            return None
14776e6818aSopenharmony_ci        elif not isinstance(retry_test_list, list):
14876e6818aSopenharmony_ci            err_msg = ErrorMessage.TestCase.Code_0203005
14976e6818aSopenharmony_ci            self.log.error(err_msg)
15076e6818aSopenharmony_ci            raise DeviceTestError(err_msg)
15176e6818aSopenharmony_ci
15276e6818aSopenharmony_ci        elif len(retry_test_list) == 1 and "#" not in str(retry_test_list[0]):
15376e6818aSopenharmony_ci            return None
15476e6818aSopenharmony_ci        else:
15576e6818aSopenharmony_ci            history_case_list = []
15676e6818aSopenharmony_ci            history_case_dict = dict()
15776e6818aSopenharmony_ci            retry_case_list = []
15876e6818aSopenharmony_ci            for abd_file_path in self.run_list:
15976e6818aSopenharmony_ci                base_file_name = get_base_name(abd_file_path)
16076e6818aSopenharmony_ci                if base_file_name not in history_case_dict.keys():
16176e6818aSopenharmony_ci                    history_case_dict.update({base_file_name: []})
16276e6818aSopenharmony_ci                history_case_dict.get(base_file_name).append(abd_file_path)
16376e6818aSopenharmony_ci                history_case_list.append(base_file_name)
16476e6818aSopenharmony_ci            self.log.debug("history case list:{}".format(history_case_list))
16576e6818aSopenharmony_ci
16676e6818aSopenharmony_ci            for _value in retry_test_list:
16776e6818aSopenharmony_ci                case_id = str(_value).split("#")[0]
16876e6818aSopenharmony_ci                if case_id in history_case_dict.keys():
16976e6818aSopenharmony_ci                    retry_case_list.append(history_case_dict.get(case_id)[0])
17076e6818aSopenharmony_ci            return retry_case_list
17176e6818aSopenharmony_ci
17276e6818aSopenharmony_ci    def parse_config(self, test_configs):
17376e6818aSopenharmony_ci        pass
17476e6818aSopenharmony_ci
17576e6818aSopenharmony_ci    def add_value_to_configs(self):
17676e6818aSopenharmony_ci        self.configs["log"] = self.log
17776e6818aSopenharmony_ci        self.configs["devices"] = self.devices
17876e6818aSopenharmony_ci        self.configs["project"] = self.project
17976e6818aSopenharmony_ci
18076e6818aSopenharmony_ci    def run(self):
18176e6818aSopenharmony_ci        self._pipeline_run()
18276e6818aSopenharmony_ci
18376e6818aSopenharmony_ci    def _pipeline_run(self):
18476e6818aSopenharmony_ci        self.running = True
18576e6818aSopenharmony_ci        aw_path = self.add_aw_path_to_sys(self.project.aw_path)
18676e6818aSopenharmony_ci        self.log.info("Executing run list {}.".format(self.run_list))
18776e6818aSopenharmony_ci
18876e6818aSopenharmony_ci        self.add_value_to_configs()
18976e6818aSopenharmony_ci
19076e6818aSopenharmony_ci        self.prepare = PrepareHandler(self.log, self.cur_case,
19176e6818aSopenharmony_ci                                      self.project, self.configs,
19276e6818aSopenharmony_ci                                      self.devices, self.run_list)
19376e6818aSopenharmony_ci        # **********混合root和非root**************
19476e6818aSopenharmony_ci        try:
19576e6818aSopenharmony_ci            for device in self.devices:
19676e6818aSopenharmony_ci                if hasattr(device, "is_root"):
19776e6818aSopenharmony_ci                    DeviceRoot.is_root_device = device.is_root
19876e6818aSopenharmony_ci                    self.log.debug(DeviceRoot.is_root_device)
19976e6818aSopenharmony_ci                    setattr(device, "is_device_root", DeviceRoot.is_root_device)
20076e6818aSopenharmony_ci
20176e6818aSopenharmony_ci        except Exception as _:
20276e6818aSopenharmony_ci            self.log.error('set branch api error.')
20376e6818aSopenharmony_ci        # **************混合root和非root end**********************
20476e6818aSopenharmony_ci        self.prepare.run_prepare()
20576e6818aSopenharmony_ci
20676e6818aSopenharmony_ci        for test_cls_name in self.run_list:
20776e6818aSopenharmony_ci            case_name = get_base_name(test_cls_name)
20876e6818aSopenharmony_ci            if self.project.record.is_shutdown(raise_exception=False):
20976e6818aSopenharmony_ci                break
21076e6818aSopenharmony_ci            self.log.info("Executing test class {}".format(test_cls_name))
21176e6818aSopenharmony_ci            self.project.execute_case_name = case_name
21276e6818aSopenharmony_ci            self.run_test_class(test_cls_name, case_name)
21376e6818aSopenharmony_ci        self.prepare.run_prepare(is_teardown=True)
21476e6818aSopenharmony_ci        clean_sys_resource(file_path=aw_path)
21576e6818aSopenharmony_ci        DeccVariable.reset()
21676e6818aSopenharmony_ci
21776e6818aSopenharmony_ci    def add_aw_path_to_sys(self, aw_path):
21876e6818aSopenharmony_ci
21976e6818aSopenharmony_ci        sys_aw_path = os.path.dirname(aw_path)
22076e6818aSopenharmony_ci        if os.path.exists(sys_aw_path):
22176e6818aSopenharmony_ci            sys.path.insert(1, sys_aw_path)
22276e6818aSopenharmony_ci            self.log.info("add {} to sys path.".format(sys_aw_path))
22376e6818aSopenharmony_ci            return sys_aw_path
22476e6818aSopenharmony_ci        return None
22576e6818aSopenharmony_ci
22676e6818aSopenharmony_ci    def run_test_class(self, case_path, case_name):
22776e6818aSopenharmony_ci        """Instantiates and executes a test class.
22876e6818aSopenharmony_ci        If the test cases list is not None, all the test cases in the test
22976e6818aSopenharmony_ci        class should be executed.
23076e6818aSopenharmony_ci        Args:
23176e6818aSopenharmony_ci            case_path: case path
23276e6818aSopenharmony_ci            case_name: case name
23376e6818aSopenharmony_ci        Returns:
23476e6818aSopenharmony_ci            A tuple, with the number of cases passed at index 0, and the total
23576e6818aSopenharmony_ci            number of test cases at index 1.
23676e6818aSopenharmony_ci        """
23776e6818aSopenharmony_ci        # 开始收集日志
23876e6818aSopenharmony_ci        case_log_buffer_hdl = add_log_caching_handler()
23976e6818aSopenharmony_ci
24076e6818aSopenharmony_ci        tests = "__init__"
24176e6818aSopenharmony_ci        case_result = RunResult.FAILED
24276e6818aSopenharmony_ci        start_time = get_cst_time()
24376e6818aSopenharmony_ci        case_dir_path = get_dir_path(case_path)
24476e6818aSopenharmony_ci        test_cls_instance = None
24576e6818aSopenharmony_ci
24676e6818aSopenharmony_ci        # 用例测试结果的拓展内容
24776e6818aSopenharmony_ci        result_content = None
24876e6818aSopenharmony_ci        try:
24976e6818aSopenharmony_ci            self.project.cur_case_full_path = case_path
25076e6818aSopenharmony_ci            DeccVariable.set_cur_case_obj(self.cur_case)
25176e6818aSopenharmony_ci            test_cls = import_from_file(case_dir_path, case_name)
25276e6818aSopenharmony_ci            self.log.info("Success to import {}.".format(case_name))
25376e6818aSopenharmony_ci            with test_cls(self.configs) as test_cls_instance:
25476e6818aSopenharmony_ci                self.cur_case.set_case_instance(test_cls_instance)
25576e6818aSopenharmony_ci                test_cls_instance.run()
25676e6818aSopenharmony_ci
25776e6818aSopenharmony_ci            tests = test_cls_instance.tests
25876e6818aSopenharmony_ci            start_time = test_cls_instance.start_time
25976e6818aSopenharmony_ci
26076e6818aSopenharmony_ci            case_result = test_cls_instance.result
26176e6818aSopenharmony_ci            error_msg = test_cls_instance.error_msg
26276e6818aSopenharmony_ci            result_content = getattr(test_cls_instance, "result_content", None)
26376e6818aSopenharmony_ci        except ImportError as exception:
26476e6818aSopenharmony_ci            error_msg = str(exception)
26576e6818aSopenharmony_ci            self.log.error(error_msg)
26676e6818aSopenharmony_ci            self.log.error(traceback.format_exc())
26776e6818aSopenharmony_ci        except Exception as exception:
26876e6818aSopenharmony_ci            error_msg = ErrorMessage.TestCase.Code_0203002.format(exception)
26976e6818aSopenharmony_ci            self.log.error(error_msg)
27076e6818aSopenharmony_ci            self.log.error(traceback.format_exc())
27176e6818aSopenharmony_ci        if test_cls_instance:
27276e6818aSopenharmony_ci            try:
27376e6818aSopenharmony_ci                del test_cls_instance
27476e6818aSopenharmony_ci                self.log.debug("del test_cls_instance success.")
27576e6818aSopenharmony_ci            except Exception as exception:
27676e6818aSopenharmony_ci                self.log.warning("del test_cls_instance exception. {}".format(exception))
27776e6818aSopenharmony_ci
27876e6818aSopenharmony_ci        Binder.notify_stage(CaseEnd(case_name, case_result, error_msg))
27976e6818aSopenharmony_ci
28076e6818aSopenharmony_ci        end_time = get_cst_time()
28176e6818aSopenharmony_ci        environment = self.configs.get("request").config.environment
28276e6818aSopenharmony_ci        steps = self.cur_case.get_steps_info()
28376e6818aSopenharmony_ci        # 停止收集日志
28476e6818aSopenharmony_ci        del_log_caching_handler(case_log_buffer_hdl)
28576e6818aSopenharmony_ci        # 生成报告
28676e6818aSopenharmony_ci        case_info = {
28776e6818aSopenharmony_ci            "name": case_name,
28876e6818aSopenharmony_ci            "result": case_result,
28976e6818aSopenharmony_ci            "begin": start_time.strftime("%Y-%m-%d %H:%M:%S"),
29076e6818aSopenharmony_ci            "end": end_time.strftime("%Y-%m-%d %H:%M:%S"),
29176e6818aSopenharmony_ci            'elapsed': calculate_elapsed_time(start_time, end_time),
29276e6818aSopenharmony_ci            "error": error_msg,
29376e6818aSopenharmony_ci            "logs": "",
29476e6818aSopenharmony_ci            "devices": [] if environment is None else environment.get_description(),
29576e6818aSopenharmony_ci            "steps": steps
29676e6818aSopenharmony_ci        }
29776e6818aSopenharmony_ci        log_content = {
29876e6818aSopenharmony_ci            "content": get_caching_logs(case_log_buffer_hdl)
29976e6818aSopenharmony_ci        }
30076e6818aSopenharmony_ci        round_folder = f"round{self._repeat_round}" if self._repeat > 1 else ""
30176e6818aSopenharmony_ci        report_path = os.path.join("details", round_folder, case_name + ".html")
30276e6818aSopenharmony_ci        to_file = os.path.join(self.project.task_report_dir, report_path)
30376e6818aSopenharmony_ci        generate_report(to_file, case=case_info, logs=log_content)
30476e6818aSopenharmony_ci        steps.clear()
30576e6818aSopenharmony_ci        del case_log_buffer_hdl
30676e6818aSopenharmony_ci        self.cur_case.set_case_instance(None)
30776e6818aSopenharmony_ci        self.record_current_case_result(
30876e6818aSopenharmony_ci            case_name, tests, case_result, start_time, error_msg, report_path,
30976e6818aSopenharmony_ci            result_content=result_content)
31076e6818aSopenharmony_ci        return case_result, error_msg
31176e6818aSopenharmony_ci
31276e6818aSopenharmony_ci    def record_current_case_result(self, case_name, tests, case_result,
31376e6818aSopenharmony_ci                                   start_time, error_msg, report, **kwargs):
31476e6818aSopenharmony_ci        test_result = self.record_cls_result(
31576e6818aSopenharmony_ci            case_name, tests, case_result, start_time, error_msg, report, **kwargs)
31676e6818aSopenharmony_ci        self.log.debug("test result: {}".format(test_result))
31776e6818aSopenharmony_ci        self.test_results.append(test_result)
31876e6818aSopenharmony_ci        self.upload_result_handler.report_handler.test_results.append(test_result)
31976e6818aSopenharmony_ci
32076e6818aSopenharmony_ci    def stop(self):
32176e6818aSopenharmony_ci        """
32276e6818aSopenharmony_ci        Releases resources from test run. Should be called right after run()
32376e6818aSopenharmony_ci        finishes.
32476e6818aSopenharmony_ci        """
32576e6818aSopenharmony_ci        if self.running:
32676e6818aSopenharmony_ci            self.running = False
32776e6818aSopenharmony_ci
32876e6818aSopenharmony_ci    @staticmethod
32976e6818aSopenharmony_ci    def record_cls_result(case_name, tests_step, result, start_time, error, report, **kwargs):
33076e6818aSopenharmony_ci        dict_result = {
33176e6818aSopenharmony_ci            "case_name": case_name,
33276e6818aSopenharmony_ci            "tests_step": tests_step or "__init__",
33376e6818aSopenharmony_ci            "result": result or RunResult.FAILED,
33476e6818aSopenharmony_ci            "start_time": start_time or get_cst_time(),
33576e6818aSopenharmony_ci            "error": error,
33676e6818aSopenharmony_ci            "end_time": get_cst_time(),
33776e6818aSopenharmony_ci            "report": report
33876e6818aSopenharmony_ci        }
33976e6818aSopenharmony_ci        dict_result.update(kwargs)
34076e6818aSopenharmony_ci        return dict_result
34176e6818aSopenharmony_ci
34276e6818aSopenharmony_ci
34376e6818aSopenharmony_ciclass TestSuiteRunner:
34476e6818aSopenharmony_ci    """
34576e6818aSopenharmony_ci    executes test suite cases
34676e6818aSopenharmony_ci    """
34776e6818aSopenharmony_ci
34876e6818aSopenharmony_ci    def __init__(self, suite, configs, devices):
34976e6818aSopenharmony_ci        self.suite = suite
35076e6818aSopenharmony_ci        self.running = False
35176e6818aSopenharmony_ci        self.configs = configs
35276e6818aSopenharmony_ci        self.devices = devices
35376e6818aSopenharmony_ci        self.log = Log
35476e6818aSopenharmony_ci        self.start_time = get_cst_time()
35576e6818aSopenharmony_ci        self.listeners = self.configs["listeners"]
35676e6818aSopenharmony_ci        self.state_machine = StateRecorder()
35776e6818aSopenharmony_ci        self.suite_name = ""
35876e6818aSopenharmony_ci
35976e6818aSopenharmony_ci    def add_value_to_configs(self):
36076e6818aSopenharmony_ci        self.configs["log"] = self.log
36176e6818aSopenharmony_ci        self.configs["devices"] = self.devices
36276e6818aSopenharmony_ci        self.configs["suite_name"] = self.suite_name
36376e6818aSopenharmony_ci
36476e6818aSopenharmony_ci    def run(self):
36576e6818aSopenharmony_ci        self.running = True
36676e6818aSopenharmony_ci        self.log.info("Executing test suite: {}.".format(self.suite))
36776e6818aSopenharmony_ci
36876e6818aSopenharmony_ci        self.suite_name = get_base_name(self.suite)
36976e6818aSopenharmony_ci        self.add_value_to_configs()
37076e6818aSopenharmony_ci        self.run_test_suite(self.suite)
37176e6818aSopenharmony_ci
37276e6818aSopenharmony_ci    def run_test_suite(self, test_cls_name):
37376e6818aSopenharmony_ci        """Instantiates and executes a test class.
37476e6818aSopenharmony_ci        If the test cases list is not None, all the test cases in the test
37576e6818aSopenharmony_ci        class should be executed.
37676e6818aSopenharmony_ci        Args:
37776e6818aSopenharmony_ci            test_cls_name: Name of the test class to execute.
37876e6818aSopenharmony_ci        Returns:
37976e6818aSopenharmony_ci            A tuple, with the number of cases passed at index 0, and the total
38076e6818aSopenharmony_ci            number of test cases at index 1.
38176e6818aSopenharmony_ci        """
38276e6818aSopenharmony_ci        suite_dir_path = get_dir_path(test_cls_name)
38376e6818aSopenharmony_ci        test_cls_instance = None
38476e6818aSopenharmony_ci        self.handle_suites_started()
38576e6818aSopenharmony_ci        self.handle_suite_started()
38676e6818aSopenharmony_ci        try:
38776e6818aSopenharmony_ci            test_cls = import_from_file(suite_dir_path, self.suite_name)
38876e6818aSopenharmony_ci            self.log.info("Success to import {}.".format(self.suite_name))
38976e6818aSopenharmony_ci            self.configs["cur_suite"] = test_cls
39076e6818aSopenharmony_ci            with test_cls(self.configs, suite_dir_path) as test_cls_instance:
39176e6818aSopenharmony_ci                test_cls_instance.run()
39276e6818aSopenharmony_ci
39376e6818aSopenharmony_ci            error_msg = test_cls_instance.error_msg
39476e6818aSopenharmony_ci            self.handle_suite_ended(test_cls_instance)
39576e6818aSopenharmony_ci        except Exception as e:
39676e6818aSopenharmony_ci            error_msg = ErrorMessage.TestCase.Code_0203017.format(e)
39776e6818aSopenharmony_ci            self.log.error(error_msg)
39876e6818aSopenharmony_ci            self.log.error(traceback.format_exc())
39976e6818aSopenharmony_ci        self.handle_suites_ended(error_msg)
40076e6818aSopenharmony_ci        result_path = os.path.join(self.configs["report_path"], "result")
40176e6818aSopenharmony_ci        report_file = os.path.join(result_path, "%s.xml" % self.suite_name)
40276e6818aSopenharmony_ci        os.makedirs(result_path, exist_ok=True)
40376e6818aSopenharmony_ci        check_result_report("", report_file, error_message=error_msg)
40476e6818aSopenharmony_ci        if test_cls_instance:
40576e6818aSopenharmony_ci            try:
40676e6818aSopenharmony_ci                del test_cls_instance
40776e6818aSopenharmony_ci                self.log.debug("del test suite instance success.")
40876e6818aSopenharmony_ci            except Exception as e:
40976e6818aSopenharmony_ci                self.log.warning("del test suite instance exception. "
41076e6818aSopenharmony_ci                                 "Exception: {}".format(e))
41176e6818aSopenharmony_ci        return error_msg
41276e6818aSopenharmony_ci
41376e6818aSopenharmony_ci    def stop(self):
41476e6818aSopenharmony_ci        """
41576e6818aSopenharmony_ci        Releases resources from test run. Should be called right after run()
41676e6818aSopenharmony_ci        finishes.
41776e6818aSopenharmony_ci        """
41876e6818aSopenharmony_ci        if self.running:
41976e6818aSopenharmony_ci            self.running = False
42076e6818aSopenharmony_ci
42176e6818aSopenharmony_ci    def handle_suites_started(self):
42276e6818aSopenharmony_ci        self.state_machine.get_suites(reset=True)
42376e6818aSopenharmony_ci        test_suites = self.state_machine.get_suites()
42476e6818aSopenharmony_ci        test_suites.suites_name = self.suite_name
42576e6818aSopenharmony_ci        test_suites.test_num = 0
42676e6818aSopenharmony_ci        for listener in self.listeners:
42776e6818aSopenharmony_ci            suite_report = copy.copy(test_suites)
42876e6818aSopenharmony_ci            listener.__started__(LifeCycle.TestSuites, suite_report)
42976e6818aSopenharmony_ci
43076e6818aSopenharmony_ci    def handle_suites_ended(self, error_msg):
43176e6818aSopenharmony_ci        suites = self.state_machine.get_suites()
43276e6818aSopenharmony_ci        suites.is_completed = True
43376e6818aSopenharmony_ci        suites.stacktrace = error_msg
43476e6818aSopenharmony_ci        for listener in self.listeners:
43576e6818aSopenharmony_ci            listener.__ended__(LifeCycle.TestSuites, suites)
43676e6818aSopenharmony_ci
43776e6818aSopenharmony_ci    def handle_suite_started(self):
43876e6818aSopenharmony_ci        self.state_machine.suite(reset=True)
43976e6818aSopenharmony_ci        self.state_machine.running_test_index = 0
44076e6818aSopenharmony_ci        test_suite = self.state_machine.suite()
44176e6818aSopenharmony_ci        test_suite.suite_name = self.suite_name
44276e6818aSopenharmony_ci        test_suite.test_num = 0
44376e6818aSopenharmony_ci        for listener in self.listeners:
44476e6818aSopenharmony_ci            suite_report = copy.copy(test_suite)
44576e6818aSopenharmony_ci            listener.__started__(LifeCycle.TestSuite, suite_report)
44676e6818aSopenharmony_ci
44776e6818aSopenharmony_ci    def handle_suite_ended(self, testsuite_cls):
44876e6818aSopenharmony_ci        suite = self.state_machine.suite()
44976e6818aSopenharmony_ci        suites = self.state_machine.get_suites()
45076e6818aSopenharmony_ci        self.handle_one_case_result(testsuite_cls)
45176e6818aSopenharmony_ci        suite.is_completed = True
45276e6818aSopenharmony_ci        # 设置测试套的报告路径
45376e6818aSopenharmony_ci        suite.report = testsuite_cls.suite_report_path
45476e6818aSopenharmony_ci        for listener in self.listeners:
45576e6818aSopenharmony_ci            listener.__ended__(LifeCycle.TestSuite, copy.copy(suite), is_clear=True)
45676e6818aSopenharmony_ci        suites.run_time += suite.run_time
45776e6818aSopenharmony_ci
45876e6818aSopenharmony_ci    def handle_one_case_result(self, testsuite_cls):
45976e6818aSopenharmony_ci        status_dict = {RunResult.PASSED: ResultCode.PASSED,
46076e6818aSopenharmony_ci                       RunResult.FAILED: ResultCode.FAILED,
46176e6818aSopenharmony_ci                       RunResult.BLOCKED: ResultCode.BLOCKED,
46276e6818aSopenharmony_ci                       "ignore": ResultCode.SKIPPED}
46376e6818aSopenharmony_ci        for case_name, case_result in testsuite_cls.case_result.items():
46476e6818aSopenharmony_ci            result = case_result.get("result")
46576e6818aSopenharmony_ci            error = case_result.get("error")
46676e6818aSopenharmony_ci            run_time = case_result.get("run_time")
46776e6818aSopenharmony_ci            report = case_result.get("report")
46876e6818aSopenharmony_ci            result_content = case_result.get("result_content")
46976e6818aSopenharmony_ci
47076e6818aSopenharmony_ci            test_result = self.state_machine.test(reset=True)
47176e6818aSopenharmony_ci            test_suite = self.state_machine.suite()
47276e6818aSopenharmony_ci            test_result.test_class = test_suite.suite_name
47376e6818aSopenharmony_ci            test_result.test_name = case_name
47476e6818aSopenharmony_ci            test_result.code = status_dict.get(result).value
47576e6818aSopenharmony_ci            test_result.stacktrace = error
47676e6818aSopenharmony_ci            test_result.run_time = run_time
47776e6818aSopenharmony_ci            test_result.report = report
47876e6818aSopenharmony_ci            if result_content:
47976e6818aSopenharmony_ci                test_result.result_content = result_content
48076e6818aSopenharmony_ci            test_result.current = self.state_machine.running_test_index + 1
48176e6818aSopenharmony_ci
48276e6818aSopenharmony_ci            self.state_machine.suite().run_time += run_time
48376e6818aSopenharmony_ci            for listener in self.listeners:
48476e6818aSopenharmony_ci                listener.__started__(
48576e6818aSopenharmony_ci                    LifeCycle.TestCase, copy.copy(test_result))
48676e6818aSopenharmony_ci            test_suites = self.state_machine.get_suites()
48776e6818aSopenharmony_ci            test_suites.test_num += 1
48876e6818aSopenharmony_ci            for listener in self.listeners:
48976e6818aSopenharmony_ci                listener.__ended__(
49076e6818aSopenharmony_ci                    LifeCycle.TestCase, copy.copy(test_result))
49176e6818aSopenharmony_ci            self.state_machine.running_test_index += 1
492