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