• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env python3
2# coding=utf-8
3
4#
5# Copyright (c) Huawei Device Co., Ltd. 2025. All right reserved.
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
20from typing import Dict, List, Union
21from xml.etree import ElementTree
22
23from _core.constants import Cluster, ConfigConst
24from _core.error import ErrorMessage
25from xdevice import platform_logger
26from ..models import TaskInfo
27from ..runner import Runner
28
29LOG = platform_logger("Worker")
30
31
32def new_element(tag: str, attrib: dict = None, text: str = None):
33    """
34    tag   : element's tag
35    attrib: element's attribute
36    text  : element's text
37    """
38    if attrib is None:
39        attrib = {}
40    ele = ElementTree.Element(tag, attrib)
41    ele.text = text
42    return ele
43
44
45def element_tostring(element: ElementTree.Element):
46    return ElementTree.tostring(element).decode()
47
48
49class UserConfig:
50
51    def __init__(self, devices: List[Dict[str, Union[int, str]]], testcase_dir: str, resource_dir: str, **kwargs):
52        """
53        devices: test devices
54        testcase_dir: testcase's path
55        resource_dir: resource's path
56        """
57        self.devices = devices
58        self.testcase_dir = testcase_dir
59        self.resource_dir = resource_dir
60        self.kwargs = kwargs
61
62        self._cfg_root = None
63
64    def _get_config(self, tag: str, clear: bool = True):
65        """获取配置节点,获取失败则新建"""
66        element = self._cfg_root.find(tag)
67        if element is not None:
68            if clear:
69                element.clear()
70        else:
71            element = new_element(tag)
72            self._cfg_root.append(element)
73        return element
74
75    def _get_devices(self):
76
77        def inner_add(_label, _device):
78            if _label not in devices.keys():
79                devices[_label] = []
80            devices.get(_label).append(_device)
81
82        devices = {}
83        for dev in self.devices:
84            sn = dev.get("sn")
85            if not sn:
86                continue
87            device = {
88                "ip": "127.0.0.1",
89                "port": "8710",
90                "sn": sn
91            }
92            inner_add("ohos", device)
93        return devices
94
95    @staticmethod
96    def _build_device(label, devices):
97        """build default device"""
98        usb_type = {"ohos": "usb-hdc"}
99        attrib = {"type": usb_type.get(label, ""), "label": label}
100        ele_device = new_element("device", attrib=attrib)
101        for dev in devices:
102            ele_info = new_element("info", attrib=dev)
103            ele_device.append(ele_info)
104        return ele_device
105
106    def _set_root(self):
107        """优先读取测试工程里的配置文件作为模板,否则使用这里代码设定的配置项"""
108        config_path = os.path.join(self._get_project_path(), "config", "user_config.xml")
109        if os.path.exists(config_path):
110            try:
111                root = ElementTree.parse(config_path).getroot()
112                if root.find("taskargs") is not None:
113                    self._cfg_root = root
114                    return
115            except ElementTree.ParseError as e:
116                LOG.error(e)
117        self._cfg_root = new_element("user_config")
118
119    def _set_environment(self):
120        environment = self._get_config("environment")
121        for label, devices in self._get_devices().items():
122            ele_device = self._build_device(label, devices)
123            environment.append(ele_device)
124
125    def _set_testcases(self):
126        ele_dir = new_element(ConfigConst.tag_dir, text=self.testcase_dir)
127        testcases = self._get_config("testcases")
128        testcases.append(ele_dir)
129
130    def _set_resource(self):
131        ele_dir = new_element(ConfigConst.tag_dir, text=self.resource_dir)
132        resource = self._get_config("resource")
133        resource.append(ele_dir)
134
135    def _set_device_log(self):
136        device_log = self._get_config("devicelog", clear=False)
137        config = {
138            ConfigConst.tag_enable: "ON",
139            ConfigConst.tag_loglevel: "INFO",
140            ConfigConst.tag_dir: ""
141        }
142        for tag, text in config.items():
143            if device_log.find(tag) is None:
144                device_log.append(new_element(tag, text=text))
145
146    def _set_log_level(self):
147        log_level = self._get_config(ConfigConst.tag_loglevel)
148        log_level.text = "DEBUG"
149
150    def _get_project_path(self):
151        case_dir = self.testcase_dir
152        return os.path.dirname(case_dir) if case_dir.endswith("testcases") else case_dir
153
154    def generation(self):
155        self._set_root()
156        self._set_environment()
157        self._set_testcases()
158        self._set_resource()
159        self._set_device_log()
160        self._set_log_level()
161        return "".join([line.strip() for line in element_tostring(self._cfg_root).split("\n")])
162
163
164class WorkerRunner(Runner):
165
166    def __init__(self, task_info: dict):
167        super().__init__(TaskInfo(**task_info))
168
169        self.report_path = os.path.join(Cluster.report_root_path, self.task_id, self.task_info.block_id)
170
171    def run(self):
172        os.makedirs(self.report_path, exist_ok=True)
173        try:
174            devices = self.task_info.devices
175            if not devices:
176                raise Exception(ErrorMessage.Cluster.Code_0104034)
177            self.prepare_project()
178            testcase_path = os.path.join(self.project_path, "testcases")
179            if not os.path.exists(testcase_path):
180                testcase_path = self.project_path
181            resource_path = os.path.join(self.project_path, "resource")
182            if not os.path.exists(resource_path):
183                resource_path = self.project_path
184            case_list = ";".join(self.case_names)
185            env_cfg = UserConfig(devices, testcase_path, resource_path).generation()
186            command = f"run -l {case_list} -env {env_cfg} -rp {self.report_path}"
187            LOG.info(f"run command: {command}")
188            from xdevice.__main__ import main_process
189            main_process(command)
190        except Exception as e:
191            LOG.error(e)
192            self.mark_cases_error(self.case_names, str(e))
193