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 os
2076e6818aSopenharmony_ciimport traceback
2176e6818aSopenharmony_ciimport platform
2276e6818aSopenharmony_cifrom xml.etree import ElementTree
2376e6818aSopenharmony_ci
2476e6818aSopenharmony_cifrom devicetest.core.exception import TestPrepareError
2576e6818aSopenharmony_cifrom devicetest.core.constants import RunResult
2676e6818aSopenharmony_cifrom devicetest.error import ErrorMessage
2776e6818aSopenharmony_cifrom devicetest.utils.util import get_base_name
2876e6818aSopenharmony_cifrom devicetest.utils.util import import_from_file
2976e6818aSopenharmony_ci
3076e6818aSopenharmony_ci
3176e6818aSopenharmony_ciclass PrepareHandler:
3276e6818aSopenharmony_ci
3376e6818aSopenharmony_ci    def __init__(self, log, cur_case, project, configs, devices, run_list):
3476e6818aSopenharmony_ci        self.log = log
3576e6818aSopenharmony_ci        self.cur_case = cur_case
3676e6818aSopenharmony_ci        self.project = project
3776e6818aSopenharmony_ci        self.configs = configs
3876e6818aSopenharmony_ci        self.devices = devices
3976e6818aSopenharmony_ci        self.is_run_prepare = False
4076e6818aSopenharmony_ci        self.parse_test_list(run_list)
4176e6818aSopenharmony_ci
4276e6818aSopenharmony_ci    def parse_prepare_config(self, case_path, xml_path):
4376e6818aSopenharmony_ci        try:
4476e6818aSopenharmony_ci            self.log.debug("parse prepare config case path:{}".
4576e6818aSopenharmony_ci                           format(case_path))
4676e6818aSopenharmony_ci            case_name = get_base_name(case_path)
4776e6818aSopenharmony_ci            prepares = ElementTree.parse(xml_path).findall("prepare")
4876e6818aSopenharmony_ci            for cls in prepares:
4976e6818aSopenharmony_ci                cls_name = get_base_name(cls.attrib["class"].strip())
5076e6818aSopenharmony_ci                for case in cls.findall("testcase"):
5176e6818aSopenharmony_ci                    name = get_base_name(case.attrib["name"].strip())
5276e6818aSopenharmony_ci                    if name and case_name == name:
5376e6818aSopenharmony_ci                        if self.flash_prepare_config(case_name, cls_name):
5476e6818aSopenharmony_ci                            break
5576e6818aSopenharmony_ci        except Exception:
5676e6818aSopenharmony_ci            self.log.debug(traceback.format_exc())
5776e6818aSopenharmony_ci            self.log.error("parse prepare config exception error.")
5876e6818aSopenharmony_ci
5976e6818aSopenharmony_ci    def flash_prepare_config(self, case_name, cls_name):
6076e6818aSopenharmony_ci        if cls_name not in self.project.prepare.config.keys():
6176e6818aSopenharmony_ci            self.project.prepare.config[cls_name] = {}
6276e6818aSopenharmony_ci            self.project.prepare.config[cls_name]['status'] = 'unexecuted'
6376e6818aSopenharmony_ci            self.project.prepare.config[cls_name]['cases'] = []
6476e6818aSopenharmony_ci        if case_name not in self.project.prepare.config[cls_name]['cases']:
6576e6818aSopenharmony_ci            self.project.prepare.config[cls_name]['cases'].append(case_name)
6676e6818aSopenharmony_ci            return True
6776e6818aSopenharmony_ci        return False
6876e6818aSopenharmony_ci
6976e6818aSopenharmony_ci    def parse_test_list(self, test_list):
7076e6818aSopenharmony_ci        """Parse user provided test list into internal format for test_runner.
7176e6818aSopenharmony_ci        """
7276e6818aSopenharmony_ci        if not self.project.prepare.path:
7376e6818aSopenharmony_ci            return
7476e6818aSopenharmony_ci        xml_path = os.path.join(self.project.prepare.path, 'prepare.xml')
7576e6818aSopenharmony_ci        self.log.debug("prepare xml path:{}".format(xml_path))
7676e6818aSopenharmony_ci        if os.access(xml_path, os.F_OK):
7776e6818aSopenharmony_ci            for elem in test_list:
7876e6818aSopenharmony_ci                self._parse_one_test_specifier(elem, xml_path)
7976e6818aSopenharmony_ci            self.log.debug("prepare config:{}".format(
8076e6818aSopenharmony_ci                self.project.prepare.config))
8176e6818aSopenharmony_ci            if self.project.prepare.config:
8276e6818aSopenharmony_ci                self.is_run_prepare = True
8376e6818aSopenharmony_ci        else:
8476e6818aSopenharmony_ci            self.log.warning(
8576e6818aSopenharmony_ci                "{} not exists, please check.".format(xml_path))
8676e6818aSopenharmony_ci
8776e6818aSopenharmony_ci    def _parse_one_test_specifier(self, item, xml_path):
8876e6818aSopenharmony_ci        sys_type = platform.system()
8976e6818aSopenharmony_ci        if sys_type == "Windows":
9076e6818aSopenharmony_ci            tokens = item.split(';')
9176e6818aSopenharmony_ci        elif sys_type == "Linux":
9276e6818aSopenharmony_ci            tokens = item.split(':')
9376e6818aSopenharmony_ci        elif sys_type == "Darwin":
9476e6818aSopenharmony_ci            tokens = item.split(':')
9576e6818aSopenharmony_ci        else:
9676e6818aSopenharmony_ci            self.log.error("system '{}' is not support".format(sys_type))
9776e6818aSopenharmony_ci            raise TestPrepareError(ErrorMessage.Common.Code_0201011)
9876e6818aSopenharmony_ci        if len(tokens) > 2:
9976e6818aSopenharmony_ci            raise TestPrepareError(ErrorMessage.Common.Code_0201012.format(item))
10076e6818aSopenharmony_ci        if len(tokens) == 1:
10176e6818aSopenharmony_ci            # This should be considered a test class name
10276e6818aSopenharmony_ci            self.parse_prepare_config(tokens[0], xml_path)
10376e6818aSopenharmony_ci        elif len(tokens) == 2:
10476e6818aSopenharmony_ci            test_cls_name, test_case_names = tokens
10576e6818aSopenharmony_ci            for elem in test_case_names.split(','):
10676e6818aSopenharmony_ci                self.validate_test_name(elem.strip())
10776e6818aSopenharmony_ci                self.parse_prepare_config(test_cls_name, xml_path)
10876e6818aSopenharmony_ci
10976e6818aSopenharmony_ci    def validate_test_name(self, name):
11076e6818aSopenharmony_ci        """Checks if a test name is valid. """
11176e6818aSopenharmony_ci        if name == "" or name is None or len(name) < 1:
11276e6818aSopenharmony_ci            raise TestPrepareError(ErrorMessage.Common.Code_0201013.format(name))
11376e6818aSopenharmony_ci
11476e6818aSopenharmony_ci    def _init_run_prepare(self, test_cls_name):
11576e6818aSopenharmony_ci        """
11676e6818aSopenharmony_ci        prepare变量清理
11776e6818aSopenharmony_ci        Args:
11876e6818aSopenharmony_ci            test_cls_name:
11976e6818aSopenharmony_ci        Returns:
12076e6818aSopenharmony_ci        """
12176e6818aSopenharmony_ci        self.cur_case.log_details_path = "./log/test_run_details.log"
12276e6818aSopenharmony_ci        self.cur_case.log_path = "./log/test_run_summary.log"
12376e6818aSopenharmony_ci        self.cur_case.set_case_screenshot_dir(self.project.test_suite_path,
12476e6818aSopenharmony_ci                                              self.project.task_report_dir,
12576e6818aSopenharmony_ci                                              test_cls_name)
12676e6818aSopenharmony_ci        self.cur_case.report_path = self.cur_case.case_screenshot_dir + ".html"
12776e6818aSopenharmony_ci        self.cur_case.case_result = RunResult.PASSED
12876e6818aSopenharmony_ci        self.cur_case.description = ""
12976e6818aSopenharmony_ci        self.cur_case.error_msg = ""
13076e6818aSopenharmony_ci        self.cur_case.status = 0
13176e6818aSopenharmony_ci        self.cur_case.image_num = 0
13276e6818aSopenharmony_ci        self.cur_case.dump_xml_num = 0
13376e6818aSopenharmony_ci
13476e6818aSopenharmony_ci    def run_prepare(self, is_teardown=False):
13576e6818aSopenharmony_ci        if not self.is_run_prepare:
13676e6818aSopenharmony_ci            return
13776e6818aSopenharmony_ci        func = 'teardown' if is_teardown else 'setup'
13876e6818aSopenharmony_ci        self.log.debug("in prepare {}".format(func))
13976e6818aSopenharmony_ci        error_msg = None
14076e6818aSopenharmony_ci        try:
14176e6818aSopenharmony_ci            for cls, val in self.project.prepare.config.items():
14276e6818aSopenharmony_ci                if self.project.prepare.path:
14376e6818aSopenharmony_ci                    prepare_path = self.project.prepare.path
14476e6818aSopenharmony_ci                else:
14576e6818aSopenharmony_ci                    prepare_path = os.path.join(
14676e6818aSopenharmony_ci                        self.project.test_suite_path, 'prepare')
14776e6818aSopenharmony_ci
14876e6818aSopenharmony_ci                self.log.debug("prepare path:{}".format(prepare_path))
14976e6818aSopenharmony_ci                test_cls_name = os.path.join(prepare_path, cls + '.py')
15076e6818aSopenharmony_ci                if not os.access(test_cls_name, os.F_OK):
15176e6818aSopenharmony_ci                    test_cls_name = os.path.join(prepare_path,
15276e6818aSopenharmony_ci                                                 cls + '.pyd')
15376e6818aSopenharmony_ci                    if not os.access(test_cls_name, os.F_OK):
15476e6818aSopenharmony_ci                        py_path = os.path.join(prepare_path, cls + '.py')
15576e6818aSopenharmony_ci                        # .py/.pyd
15676e6818aSopenharmony_ci                        msg = "{} or {}".format(py_path, py_path + "d")
15776e6818aSopenharmony_ci                        raise TestPrepareError(ErrorMessage.Common.Code_0201014.format(msg))
15876e6818aSopenharmony_ci                self.log.info("import prepare script:{}".format(cls))
15976e6818aSopenharmony_ci                self.project.cur_case_full_path = test_cls_name
16076e6818aSopenharmony_ci                test_cls = import_from_file(prepare_path, cls)
16176e6818aSopenharmony_ci                self.log.debug(
16276e6818aSopenharmony_ci                    "Success to import {}.".format(test_cls_name))
16376e6818aSopenharmony_ci                with test_cls(self.configs) as test_instance:
16476e6818aSopenharmony_ci                    if 'setup' == func:
16576e6818aSopenharmony_ci                        if 'unexecuted' == val['status']:
16676e6818aSopenharmony_ci                            self.project.prepare.config[cls][
16776e6818aSopenharmony_ci                                'status'] = 'executed'
16876e6818aSopenharmony_ci                            result = test_instance._exec_func(
16976e6818aSopenharmony_ci                                test_instance.setup)
17076e6818aSopenharmony_ci                            if not result:
17176e6818aSopenharmony_ci                                raise TestPrepareError(ErrorMessage.Common.Code_0201015)
17276e6818aSopenharmony_ci                    else:
17376e6818aSopenharmony_ci                        if 'executed' == val['status']:
17476e6818aSopenharmony_ci                            self.project.prepare.config[cls][
17576e6818aSopenharmony_ci                                'status'] = 'finsh'
17676e6818aSopenharmony_ci                            result = test_instance._exec_func(
17776e6818aSopenharmony_ci                                test_instance.teardown)
17876e6818aSopenharmony_ci                            if not result:
17976e6818aSopenharmony_ci                                self.log.warning(ErrorMessage.Common.Code_0201016)
18076e6818aSopenharmony_ci
18176e6818aSopenharmony_ci        except TestPrepareError as e:
18276e6818aSopenharmony_ci            error_msg = str(e)
18376e6818aSopenharmony_ci            self.log.error(error_msg)
18476e6818aSopenharmony_ci            self.log.error(traceback.format_exc())
18576e6818aSopenharmony_ci
18676e6818aSopenharmony_ci        except Exception as e:
18776e6818aSopenharmony_ci            error_msg = "run prepare error! {}".format(e)
18876e6818aSopenharmony_ci            self.log.error(error_msg)
18976e6818aSopenharmony_ci            self.log.error(traceback.format_exc())
19076e6818aSopenharmony_ci
19176e6818aSopenharmony_ci        finally:
19276e6818aSopenharmony_ci            self.log.debug("exit prepare {}".format(func))
19376e6818aSopenharmony_ci            if error_msg is not None:
19476e6818aSopenharmony_ci                raise TestPrepareError(error_msg)
195