• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env python3
2# coding=utf-8
3
4#
5# Copyright (c) 2022 Huawei Device Co., Ltd.
6# Licensed under the Apache License, Version 2.0 (the "License");
7# you may not use this file except in compliance with the License.
8# You may obtain a copy of the License at
9#
10#     http://www.apache.org/licenses/LICENSE-2.0
11#
12# Unless required by applicable law or agreed to in writing, software
13# distributed under the License is distributed on an "AS IS" BASIS,
14# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15# See the License for the specific language governing permissions and
16# limitations under the License.
17#
18
19import os
20import traceback
21import platform
22from xml.etree import ElementTree
23
24from devicetest.core.exception import TestPrepareError
25from devicetest.core.constants import RunResult
26from devicetest.utils.util import get_base_name
27from devicetest.utils.util import import_from_file
28
29
30class PrepareHandler():
31
32    def __init__(self, log, cur_case, project, configs, devices, run_list):
33        self.log = log
34        self.cur_case = cur_case
35        self.project = project
36        self.configs = configs
37        self.devices = devices
38        self.is_run_prepare = False
39        self.parse_test_list(run_list)
40
41    def parse_prepare_config(self, case_path, xml_path):
42        try:
43            self.log.debug("parse prepare config case path:{}".
44                           format(case_path))
45            case_name = get_base_name(case_path)
46            prepares = ElementTree.parse(xml_path).findall("prepare")
47            for cls in prepares:
48                cls_name = get_base_name(cls.attrib["class"].strip())
49                for case in cls.findall("testcase"):
50                    name = get_base_name(case.attrib["name"].strip())
51                    if name and case_name == name:
52                        if self.flash_prepare_config(case_name, cls_name):
53                            break
54        except Exception:
55            self.log.debug(traceback.format_exc())
56            self.log.error("parse prepare config exception error.")
57
58    def flash_prepare_config(self, case_name, cls_name):
59        if cls_name not in self.project.prepare.config.keys():
60            self.project.prepare.config[cls_name] = {}
61            self.project.prepare.config[cls_name]['status'] = 'unexecuted'
62            self.project.prepare.config[cls_name]['cases'] = []
63        if case_name not in self.project.prepare.config[cls_name]['cases']:
64            self.project.prepare.config[cls_name]['cases'].append(case_name)
65            return True
66        return False
67
68    def parse_test_list(self, test_list):
69        """Parse user provided test list into internal format for test_runner.
70        """
71        if not self.project.prepare.path:
72            return
73        xml_path = os.path.join(self.project.prepare.path, 'prepare.xml')
74        self.log.debug("prepare xml path:{}".format(xml_path))
75        if os.access(xml_path, os.F_OK):
76            for elem in test_list:
77                self._parse_one_test_specifier(elem, xml_path)
78            self.log.debug("prepare config:{}".format(
79                self.project.prepare.config))
80            if self.project.prepare.config:
81                self.is_run_prepare = True
82        else:
83            self.log.warning(
84                "{} not exists, please check.".format(xml_path))
85
86    def _parse_one_test_specifier(self, item, xml_path):
87        sys_type = platform.system()
88        if sys_type == "Windows":
89            tokens = item.split(';')
90        elif sys_type == "Linux":
91            tokens = item.split(':')
92        elif sys_type == "Darwin":
93            tokens = item.split(':')
94        else:
95            raise TestPrepareError("sys type error:{}".format(sys_type))
96        if len(tokens) > 2:
97            raise TestPrepareError(
98                "Syntax error in test specifier {}".format(item))
99        if len(tokens) == 1:
100            # This should be considered a test class name
101            self.parse_prepare_config(tokens[0], xml_path)
102        elif len(tokens) == 2:
103            test_cls_name, test_case_names = tokens
104            for elem in test_case_names.split(','):
105                self.validate_test_name(elem.strip())
106                self.parse_prepare_config(test_cls_name, xml_path)
107
108    def validate_test_name(self, name):
109        """Checks if a test name is valid. """
110        if name == "" or name is None or len(name) < 1:
111            raise TestPrepareError(
112                "Invalid test case name found:{},test method couldn't"
113                " be none.".format(name))
114
115    def _init_run_prepare(self, test_cls_name):
116        """
117        prepare变量清理
118        Args:
119            test_cls_name:
120        Returns:
121        """
122        self.cur_case.log_details_path = "./log/test_run_details.log"
123        self.cur_case.log_path = "./log/test_run_summary.log"
124        self.cur_case.set_case_screenshot_dir(self.project.test_suite_path,
125                                              self.project.task_report_dir,
126                                              test_cls_name)
127        self.cur_case.report_path = self.cur_case.case_screenshot_dir + ".html"
128        self.cur_case.case_result = RunResult.PASSED
129        self.cur_case.description = ""
130        self.cur_case.error_msg = ""
131        self.cur_case.status = 0
132        self.cur_case.image_num = 0
133        self.cur_case.dump_xml_num = 0
134
135    def run_prepare(self, is_teardown=False):
136        if not self.is_run_prepare:
137            return
138        func = 'teardown' if is_teardown else 'setup'
139        self.log.debug("in prepare {}".format(func))
140        error_msg = None
141        try:
142            for cls, val in self.project.prepare.config.items():
143                if self.project.prepare.path:
144                    prepare_path = self.project.prepare.path
145                else:
146                    prepare_path = os.path.join(
147                        self.project.test_suite_path, 'prepare')
148
149                self.log.debug("prepare path:{}".format(prepare_path))
150                test_cls_name = os.path.join(prepare_path, cls + '.py')
151                if not os.access(test_cls_name, os.F_OK):
152                    test_cls_name = os.path.join(prepare_path,
153                                                 cls + '.pyd')
154                    if not os.access(test_cls_name, os.F_OK):
155                        err = "Can not find prepare script '{}'.".format(
156                            os.path.join(prepare_path, cls + '.py/d'))
157                        raise TestPrepareError(err)
158                self.log.info("import prepare script:{}".format(cls))
159                self.project.cur_case_full_path = test_cls_name
160                test_cls = import_from_file(prepare_path, cls)
161                self.log.debug(
162                    "Success to import {}.".format(test_cls_name))
163                with test_cls(self.configs) as test_instance:
164                    if 'setup' == func:
165                        if 'unexecuted' == val['status']:
166                            self.project.prepare.config[cls][
167                                'status'] = 'executed'
168                            result = test_instance._exec_func(
169                                test_instance.setup)
170                            if not result:
171                                raise TestPrepareError(
172                                    "prepare's setup may be error!")
173                    else:
174                        if 'executed' == val['status']:
175                            self.project.prepare.config[cls][
176                                'status'] = 'finsh'
177                            result = test_instance._exec_func(
178                                test_instance.teardown)
179                            if not result:
180                                self.log.warning(
181                                    "prepare's teardown may be error!")
182
183        except TestPrepareError as err:
184            error_msg = "{}: {}".format(err, traceback.format_exc())
185            self.log.error(error_msg)
186
187        except Exception:
188            error_msg = "run prepare error! {}".format(traceback.format_exc())
189            self.log.error(error_msg)
190            self.log.debug(traceback.format_exc())
191
192        finally:
193            self.log.debug("exit prepare {}".format(func))
194            if error_msg is not None:
195                raise TestPrepareError(error_msg)
196