diff --git a/plugins/ohos/src/ohos/drivers/drivers.py b/plugins/ohos/src/ohos/drivers/drivers.py index 2ea4ae5..8e455f7 100644 --- a/plugins/ohos/src/ohos/drivers/drivers.py +++ b/plugins/ohos/src/ohos/drivers/drivers.py @@ -24,6 +24,7 @@ import shutil import zipfile import tempfile import stat +from collections import namedtuple from dataclasses import dataclass from xdevice import ParamError @@ -62,6 +63,7 @@ from xdevice import unlock_device from ohos.environment.dmlib import process_command_ret from ohos.environment.dmlib import DisplayOutputReceiver from ohos.testkit.kit import junit_dex_para_parse +from ohos.parser.parser import _ACE_LOG_MARKER __all__ = ["CppTestDriver", "DexTestDriver", "HapTestDriver", "JSUnitTestDriver", "JUnitTestDriver", "RemoteTestRunner", @@ -1504,7 +1506,7 @@ class RemoteDexRunner: self.config.device.execute_shell_command( command, timeout=self.config.timeout, receiver=handler, retry=0) - except ConnectionResetError as _: + except ConnectionResetError as _: # pylint:disable=undefined-variable if len(listener) == 1 and isinstance(listener[0], CollectingTestListener): LOG.info("Try subprocess ") @@ -2224,7 +2226,7 @@ class JSUnitTestDriver(IDriver): label_list, suite_info, is_suites_end = self.read_device_log_timeout( device_log_file, message_list, timeout) if not is_suites_end: - message_list.append("app Log: [end] run suites end\n") + message_list.append(_ACE_LOG_MARKER + ": [end] run suites end\n") LOG.warning("there is no suites end") if len(label_list[0]) > 0 and sum(label_list[0]) != 0: # the problem happened! when the sum of label list is not zero @@ -2242,13 +2244,13 @@ class JSUnitTestDriver(IDriver): continue # check the start label, then peek next position if i + 1 == len(label_list[0]): # next position at the tail - message_list.insert(-1, "app Log: [suite end]\n") + message_list.insert(-1, _ACE_LOG_MARKER + ": [suite end]\n") LOG.warning("there is no suite end") continue if label_list[0][i + 1] != 1: # 0 present the end label continue message_list.insert(label_list[1][i + 1], - "app Log: [suite end]\n") + _ACE_LOG_MARKER + ": [suite end]\n") LOG.warning("there is no suite end") for j in range(i + 1, len(label_list[1])): label_list[1][j] += 1 # move the index to next @@ -2338,7 +2340,7 @@ class JSUnitTestDriver(IDriver): if not line: time.sleep(5) # wait for log write to file break - if line.lower().find("jsapp:") != -1: + if line.lower().find(_ACE_LOG_MARKER + ":") != -1: if "[suites info]" in line: _, pos = re.match(".+\\[suites info]", line).span() suite_info.append(line[pos:].strip()) @@ -2389,8 +2391,7 @@ class JSUnitTestDriver(IDriver): self.config.resource_path, self.config.testcases_path) - package, ability_name, runner, testcase_timeout = \ - self._get_driver_config(json_config) + driver_config = self._get_driver_config(json_config) # bms not check release type self.config.device.execute_shell_command("bm set -d enable") # turn auto rotation off @@ -2401,7 +2402,8 @@ class JSUnitTestDriver(IDriver): # execute test case command = "aa start -p %s -n %s " \ "-s unittest %s -s rawLog true -s timeout %s" \ - % (package, ability_name, runner, testcase_timeout) + % (driver_config.package, driver_config.ability_name, + driver_config.runner, driver_config.testcase_timeout) result_value = self.config.device.execute_shell_command( command, timeout=self.timeout) if self.xml_output == "true": @@ -2409,7 +2411,7 @@ class JSUnitTestDriver(IDriver): if report_name: self.config.target_test_path = "/%s/%s/%s/%s/%s/" \ % ("sdcard", "Android", - "data", package, "cache") + "data", driver_config.package, "cache") result = ResultManager(report_name, self.config.report_path, self.config.device, @@ -2445,7 +2447,8 @@ class JSUnitTestDriver(IDriver): if not package: raise ParamError("Can't find package in config file.", error_no="03201") - return package, ability_name, runner, testcase_timeout + DriverConfig = namedtuple('DriverConfig', 'package ability_name runner testcase_timeout') + return DriverConfig(package, ability_name, runner, testcase_timeout) def run_js_outer(self, request): try: @@ -2473,6 +2476,7 @@ class JSUnitTestDriver(IDriver): timeout=30 * 1000) time.sleep(10) + self.config.device.set_device_report_path(request.config.report_path) self.config.device.connector_command("shell hilog -r", timeout=30 * 1000) self._run_jsunit_outer(config_file, request) except Exception as exception: @@ -2482,6 +2486,10 @@ class JSUnitTestDriver(IDriver): LOG.exception(self.error_message, exc_info=False, error_no="03409") raise exception finally: + serial = "{}_{}".format(str(self.config.device.__get_serial__()), time.time_ns()) + log_tar_file_name = "{}_{}".format(str(serial).replace( + ":", "_"), request.get_module_name()) + self.config.device.start_get_crash_log(log_tar_file_name) self.config.device.stop_catch_device_log() self.result = check_result_report( request.config.report_path, self.result, self.error_message) @@ -2513,6 +2521,7 @@ class JSUnitTestDriver(IDriver): 0o755) with os.fdopen(hilog_open, "a") as hilog_file_pipe: + self.config.device.clear_crash_log() self.config.device.start_catch_device_log( hilog_file_pipe=hilog_file_pipe) diff --git a/plugins/ohos/src/ohos/drivers/openharmony.py b/plugins/ohos/src/ohos/drivers/openharmony.py index 51af15d..1b233eb 100644 --- a/plugins/ohos/src/ohos/drivers/openharmony.py +++ b/plugins/ohos/src/ohos/drivers/openharmony.py @@ -17,6 +17,7 @@ # import os +import time from xdevice import ParamError from xdevice import IDriver @@ -239,6 +240,8 @@ class OHJSUnitTestDriver(IDriver): "test source '%s' not exists" % request.root.source.source_string, error_no="00110") LOG.debug("Test case file path: %s" % suite_file) + self.config.device.set_device_report_path(request.config.report_path) + hilog = get_device_log_file(request.config.report_path, request.config.device.__get_serial__() + "_" + request. get_module_name(), @@ -248,6 +251,7 @@ class OHJSUnitTestDriver(IDriver): 0o755) self.config.device.execute_shell_command(command="hilog -r") with os.fdopen(hilog_open, "a") as hilog_file_pipe: + self.config.device.clear_crash_log() self.config.device.start_catch_device_log(hilog_file_pipe=hilog_file_pipe) self._run_oh_jsunit(config_file, request) except Exception as exception: @@ -257,6 +261,10 @@ class OHJSUnitTestDriver(IDriver): LOG.exception(self.error_message, exc_info=True, error_no="03409") raise exception finally: + serial = "{}_{}".format(str(self.config.device.__get_serial__()), time.time_ns()) + log_tar_file_name = "{}_{}".format(str(serial).replace( + ":", "_"), request.get_module_name()) + self.config.device.start_get_crash_log(log_tar_file_name) self.config.device.stop_catch_device_log() self.result = check_result_report( request.config.report_path, self.result, self.error_message) @@ -291,7 +299,7 @@ class OHJSUnitTestDriver(IDriver): self.config.device.connector_command("target mount") do_module_kit_setup(request, self.kits) self.runner = OHJSUnitTestRunner(self.config) - self.runner.suite_name = request.get_module_name() + self.runner.suites_name = request.get_module_name() # execute test case self._get_runner_config(json_config) oh_jsunit_para_parse(self.runner, self.config.testargs) @@ -334,10 +342,12 @@ class OHJSUnitTestDriver(IDriver): json_config.get_driver(), False) bundle = get_config_value('bundle-name', json_config. get_driver(), False) + is_rerun = get_config_value('rerun', json_config.get_driver(), False) self.config.package_name = package self.config.module_name = module self.config.bundle_name = bundle + self.rerun = True if is_rerun == 'true' else False if not package and not module: raise ParamError("Neither package nor moodle is found" @@ -364,7 +374,7 @@ class OHJSUnitTestDriver(IDriver): test_to_run = self._collect_test_to_run() LOG.info("Collected test count is: %s" % (len(test_to_run) if test_to_run else 0)) - if not test_to_run: + if not test_to_run or not self.rerun: self.runner.run(listener) else: self._run_with_rerun(listener, test_to_run) @@ -429,7 +439,7 @@ class OHJSUnitTestDriver(IDriver): class OHJSUnitTestRunner: def __init__(self, config): self.arg_list = {} - self.suite_name = None + self.suites_name = None self.config = config self.rerun_attemp = 3 self.suite_recorder = {} @@ -459,7 +469,7 @@ class OHJSUnitTestRunner: parser_instances = [] for parser in parsers: parser_instance = parser.__class__() - parser_instance.suite_name = self.suite_name + parser_instance.suites_name = self.suite_name parser_instance.listeners = listener parser_instances.append(parser_instance) handler = ShellHandler(parser_instances) diff --git a/plugins/ohos/src/ohos/environment/device.py b/plugins/ohos/src/ohos/environment/device.py index c59df3c..181d7a8 100644 --- a/plugins/ohos/src/ohos/environment/device.py +++ b/plugins/ohos/src/ohos/environment/device.py @@ -80,7 +80,7 @@ def perform_device_action(func): except ReportException as error: self.log.exception("Generate report error!", exc_info=False) exception = error - except (ConnectionResetError, ConnectionRefusedError) as error: + except (ConnectionResetError, ConnectionRefusedError) as error: # pylint:disable=undefined-variable self.log.error("error type: %s, error: %s" % (error.__class__.__name__, error)) cmd = "hdc_std target boot" @@ -111,7 +111,6 @@ def perform_device_action(func): self.log.exception("error type: %s, error: %s" % ( error.__class__.__name__, error), exc_info=False) exception = error - raise exception return device_action @@ -409,8 +408,9 @@ class Device(IDevice): self.device_hilog_proc = None self.hilog_file_pipe = None - def start_hilog_task(self): - self._clear_crash_log() + def start_hilog_task(self, log_size="50M"): + self._sync_device_time() + self.clear_crash_log() # 先停止一下 cmd = "hilog -w stop" out = self.execute_shell_command(cmd) @@ -419,8 +419,8 @@ class Device(IDevice): out = self.execute_shell_command(cmd) cmd = "rm -rf /data/log/hilog/*" out = self.execute_shell_command(cmd) - # 开始日志任务 设置落盘文件个数最大值1000,链接https://gitee.com/openharmony/hiviewdfx_hilog - cmd = "hilog -w start -n 1000" + # 开始日志任务 设置落盘文件个数最大值1000, 单个文件20M,链接https://gitee.com/openharmony/hiviewdfx_hilog + cmd = "hilog -w start -l {} -n 1000".format(log_size) out = self.execute_shell_command(cmd) LOG.info("Execute command: {}, result is {}".format(cmd, out)) @@ -428,14 +428,14 @@ class Device(IDevice): cmd = "hilog -w stop" out = self.execute_shell_command(cmd) # 把hilog文件夹下所有文件拉出来 由于hdc不支持整个文件夹拉出只能采用先压缩再拉取文件 - cmd = "tar -zcvf /data/log/hilog_{}.tar.gz /data/log/hilog/".format(log_name) + cmd = "cd /data/log/hilog && tar -zcvf /data/log/hilog_{}.tar.gz *".format(log_name) out = self.execute_shell_command(cmd) LOG.info("Execute command: {}, result is {}".format(cmd, out)) self.pull_file("/data/log/hilog_{}.tar.gz".format(log_name), "{}/log/".format(self._device_log_path)) cmd = "rm -rf /data/log/hilog_{}.tar.gz".format(log_name) out = self.execute_shell_command(cmd) # 获取crash日志 - self._start_get_crash_log(log_name) + self.start_get_crash_log(log_name) def _get_log(self, log_cmd, *params): def filter_by_name(log_name, args): @@ -477,12 +477,11 @@ class Device(IDevice): self.pull_file(temp_path, crash_path) LOG.debug("Finish pull file: %s" % log_name) - def _start_get_crash_log(self, task_name): + def start_get_crash_log(self, task_name): log_array = list() native_crash_cmd = "ls /data/log/faultlog/temp" js_crash_cmd = '"ls /data/log/faultlog/faultlogger | grep jscrash"' block_crash_cmd = '"ls /data/log/faultlog/"' - # 获取crash日志文件 log_array.extend(self._get_log(native_crash_cmd, "cppcrash")) log_array.extend(self._get_log(js_crash_cmd, "jscrash")) @@ -493,18 +492,15 @@ class Device(IDevice): log_name = log_name.strip() self.get_cur_crash_log(crash_path, log_name) - def _clear_crash_log(self): - self._sync_device_time() - clear_block_crash_cmd = "rm -rf /data/log/faultlog/" + def clear_crash_log(self): + clear_block_crash_cmd = "rm -f /data/log/faultlog/*" + clear_native_crash_cmd = "rm -f /data/log/faultlog/temp/*" + clear_debug_crash_cmd = "rm -f /data/log/faultlog/debug/*" + clear_js_crash_cmd = "rm -f /data/log/faultlog/faultlogger/*" self.execute_shell_command(clear_block_crash_cmd) - mkdir_block_crash_cmd = "mkdir /data/log/faultlog/" - mkdir_native_crash_cmd = "mkdir /data/log/faultlog/temp" - mkdir_debug_crash_cmd = "mkdir /data/log/faultlog/debug" - mkdir_js_crash_cmd = "mkdir /data/log/faultlog/faultlogger" - self.execute_shell_command(mkdir_block_crash_cmd) - self.execute_shell_command(mkdir_native_crash_cmd) - self.execute_shell_command(mkdir_js_crash_cmd) - self.execute_shell_command(mkdir_debug_crash_cmd) + self.execute_shell_command(clear_native_crash_cmd) + self.execute_shell_command(clear_debug_crash_cmd) + self.execute_shell_command(clear_js_crash_cmd) def _sync_device_time(self): # 先同步PC和设备的时间 @@ -525,6 +521,14 @@ class Device(IDevice): abort_on_exception=True).strip() if stdout: LOG.debug(stdout) + if "fail" in stdout: + cmd = ["hdc_std", "list", "targets"] + result = exec_cmd(cmd) + LOG.debug("exec_cmd list targets: {}, current device_sn: {}".format(result, self.device_sn)) + if self.device_sn in result: + return "1" + else: + return "0" return stdout def set_recover_state(self, state): @@ -607,7 +611,7 @@ class Device(IDevice): try: from devicetest.controllers.openharmony import OpenHarmony OpenHarmony.install_harmony_rpc(self) - except (ModuleNotFoundError, ImportError) as error: + except (ModuleNotFoundError, ImportError) as error: # pylint:disable=undefined-variable self.log.debug(str(error)) self.log.error('please check devicetest extension module is exist.') raise Exception(ErrorMessage.Error_01437.Topic) @@ -632,13 +636,18 @@ class Device(IDevice): self.kill_devicetest_agent() def is_harmony_rpc_running(self): - cmd = 'ps -A | grep %s' % DEVICETEST_HAP_PACKAGE_NAME + if hasattr(self, "oh_type") and getattr(self, "oh_type") == "other": + bundle_name = DEVICETEST_HAP_PACKAGE_NAME + else: + # 由于RK上有字段截断问题,因此做出该适配 + bundle_name = "com.ohos.device" + cmd = 'ps -A | grep %s' % bundle_name rpc_running = self.execute_shell_command(cmd).strip() self.log.debug('is_rpc_running out:{}'.format(rpc_running)) cmd = 'ps -A | grep %s' % UITEST_NAME uitest_running = self.execute_shell_command(cmd).strip() self.log.debug('is_uitest_running out:{}'.format(uitest_running)) - if DEVICETEST_HAP_PACKAGE_NAME in rpc_running and UITEST_NAME in uitest_running: + if bundle_name in rpc_running and UITEST_NAME in uitest_running: return True return False @@ -650,19 +659,29 @@ class Device(IDevice): for data in out: if UITEST_NAME in data: data = data.split() - cmd = 'kill %s' % data[1] + if hasattr(self, "oh_type") and getattr(self, "oh_type") == "other": + cmd = 'kill %s' % data[1] + else: + cmd = 'kill %s' % data[0] self.execute_shell_command(cmd).strip() return def kill_devicetest_agent(self): - cmd = 'ps -A | grep %s' % DEVICETEST_HAP_PACKAGE_NAME + if hasattr(self, "oh_type") and getattr(self, "oh_type") == "other": + bundle_name = DEVICETEST_HAP_PACKAGE_NAME + index = 1 + else: + # 由于RK上有字段截断问题,因此做出该适配 + bundle_name = "com.ohos.device" + index = 0 + cmd = 'ps -A | grep %s' % bundle_name out = self.execute_shell_command(cmd).strip() self.log.debug('is_rpc_running out:{}'.format(out)) out = out.split("\n") - for data in out: - if DEVICETEST_HAP_PACKAGE_NAME in data: - data = data.split() - data = 'kill %s' % data[1] + for name in out: + if bundle_name in name: + name = name.split() + cmd = 'kill %s' % name[index] self.execute_shell_command(cmd).strip() self.log.debug('stop devicetest ability success.') return @@ -703,10 +722,10 @@ class Device(IDevice): self._h_port, self.d_port) self.connector_command(cmd) try: - self._proxy.init(port=self._h_port, addr=self.host, _ad=self) + self._proxy.init(port=self._h_port, addr=self.host, device=self) except Exception as _: time.sleep(3) - self._proxy.init(port=self._h_port, addr=self.host, _ad=self) + self._proxy.init(port=self._h_port, addr=self.host, device=self) if self._uitestdeamon is not None: self._uitestdeamon.init(self) diff --git a/plugins/ohos/src/ohos/parser/parser.py b/plugins/ohos/src/ohos/parser/parser.py index 1b127d0..f9a81e1 100644 --- a/plugins/ohos/src/ohos/parser/parser.py +++ b/plugins/ohos/src/ohos/parser/parser.py @@ -35,7 +35,7 @@ from xdevice import CommonParserType __all__ = ["CppTestParser", "CppTestListParser", "JunitParser", "JSUnitParser", "OHKernelTestParser", "OHJSUnitTestParser", - "OHJSUnitTestListParser"] + "OHJSUnitTestListParser", "_ACE_LOG_MARKER"] _INFORMATIONAL_MARKER = "[----------]" _START_TEST_RUN_MARKER = "[==========] Running" @@ -1017,7 +1017,7 @@ class OHJSUnitTestParser(IParser): def __init__(self): self.state_machine = StateRecorder() - self.suite_name = "" + self.suites_name = "" self.listeners = [] self.current_key = None self.current_value = None @@ -1026,7 +1026,7 @@ class OHJSUnitTestParser(IParser): self.test_run_finished = False def get_suite_name(self): - return self.suite_name + return self.suites_name def get_listeners(self): return self.listeners @@ -1160,7 +1160,7 @@ class OHJSUnitTestParser(IParser): for listener in self.get_listeners(): suite = copy.copy(suite_result) listener.__ended__(LifeCycle.TestSuites, suite, - suites_name=self.suite_name) + suites_name=self.suites_name) self.state_machine.current_suite = None def mark_test_as_blocked(self, test): diff --git a/plugins/ohos/src/ohos/testkit/kit.py b/plugins/ohos/src/ohos/testkit/kit.py index e2d8677..ac62cdb 100644 --- a/plugins/ohos/src/ohos/testkit/kit.py +++ b/plugins/ohos/src/ohos/testkit/kit.py @@ -249,14 +249,14 @@ class PushKit(ITestKit): for root, _, files in os.walk(real_src_path): for file in files: device.connector_command( - "file send {} {}".format(os.path.join(root, file), + "file send \"{}\" \"{}\"".format(os.path.join(root, file), dst)) LOG.debug( "Push file finished from {} to {}".format( os.path.join(root, file), dst)) self.pushed_file.append(os.path.join(dst, file)) else: - device.connector_command("file send {} {}".format(real_src_path, + device.connector_command("file send \"{}\" \"{}\"".format(real_src_path, dst)) LOG.debug("Push file finished from {} to {}".format(src, dst)) self.pushed_file.append(dst) @@ -689,7 +689,7 @@ class AppInstallKit(ITestKit): LOG.error("The app file {} does not exist".format(app)) continue if hasattr(device, "is_harmony") and device.is_harmony: - device.connector_command("install {}".format(app_file)) + device.connector_command("install \"{}\"".format(app_file)) else: self.install_hap(device, app_file) self.installed_app.add(app_file) diff --git a/src/xdevice/__init__.py b/src/xdevice/__init__.py index ff43234..9032c33 100755 --- a/src/xdevice/__init__.py +++ b/src/xdevice/__init__.py @@ -50,6 +50,7 @@ from _core.constants import ProductForm from _core.constants import TestType from _core.constants import CKit from _core.constants import ConfigConst +from _core.constants import ReportConst from _core.constants import ModeType from _core.constants import TestExecType from _core.constants import ListenerType @@ -156,6 +157,7 @@ __all__ = [ "TestType", "CKit", "ConfigConst", + "ReportConst", "ModeType", "TestExecType", "ListenerType", diff --git a/src/xdevice/_core/command/console.py b/src/xdevice/_core/command/console.py index fb7815a..b542495 100644 --- a/src/xdevice/_core/command/console.py +++ b/src/xdevice/_core/command/console.py @@ -23,10 +23,12 @@ import signal import sys import threading import copy +from collections import namedtuple from _core.config.config_manager import UserConfigManager from _core.constants import SchedulerType from _core.constants import ConfigConst +from _core.constants import ReportConst from _core.constants import ModeType from _core.constants import ToolCommandType from _core.environment.manager_env import EnvironmentManager @@ -39,6 +41,7 @@ from _core.plugin import Plugin from _core.plugin import get_plugin from _core.utils import SplicingAction from _core.utils import get_instance_name +from _core.utils import is_python_satisfied from _core.report.result_reporter import ResultReporter __all__ = ["Console"] @@ -47,11 +50,12 @@ LOG = platform_logger("Console") try: if platform.system() != 'Windows': import readline -except (ModuleNotFoundError, ImportError): +except (ModuleNotFoundError, ImportError): # pylint:disable=undefined-variable LOG.warning("Readline module is not exist.") MAX_VISIBLE_LENGTH = 49 MAX_RESERVED_LENGTH = 46 +Argument = namedtuple('Argument', 'options unparsed valid_param parser') class Console(object): @@ -88,9 +92,7 @@ class Console(object): """ Main xDevice console providing user with the interface to interact """ - if sys.version < '3.7': - LOG.error("Please use python 3.7 or higher version to " - "start project") + if not is_python_satisfied(): sys.exit(0) if args is None or len(args) < 2: @@ -324,7 +326,7 @@ class Console(object): valid_param = False parser.print_help() LOG.warning("Parameter parsing system exit exception.") - return options, unparsed, valid_param, parser + return Argument(options, unparsed, valid_param, parser) @classmethod def _params_pre_processing(cls, para_list): @@ -384,16 +386,15 @@ class Console(object): Scheduler.command_queue.append(args) LOG.info("Input command: {}".format(args)) para_list = args.split() - (options, _, valid_param, parser) = self.argument_parser( - para_list) - if options is None or not valid_param: + argument = self.argument_parser( para_list) + if argument.options is None or not argument.valid_param: LOG.warning("Options is None.") return None - if options.action == ToolCommandType.toolcmd_key_run and \ - options.retry: - options = self._get_retry_options(options, parser) - if options.dry_run: - history_report_path = getattr(options, + if argument.options.action == ToolCommandType.toolcmd_key_run and \ + argument.options.retry: + argument.options = self._get_retry_options(argument.options, argument.parser) + if argument.options.dry_run: + history_report_path = getattr(argument.options, "history_report_path", "") self._list_retry_case(history_report_path) return @@ -402,12 +403,12 @@ class Console(object): SuiteReporter.clear_failed_case_list() SuiteReporter.clear_report_result() - command = options.action + command = argument.options.action if command == "": LOG.info("Command is empty.") return - self._process_command(command, options, para_list, parser) + self._process_command(command, argument.options, para_list, argument.parser) except (ParamError, ValueError, TypeError, SyntaxError, AttributeError) as exception: error_no = getattr(exception, "error_no", "00000") @@ -457,18 +458,18 @@ class Console(object): split_list = split_list[:pos] + split_list[pos+2:] history_command = " ".join(split_list) - (options, _, _, _) = self.argument_parser(history_command.split()) - options.dry_run = is_dry_run - setattr(options, "history_report_path", history_report_path) + argument = self.argument_parser(history_command.split()) + argument.options.dry_run = is_dry_run + setattr(argument.options, "history_report_path", history_report_path) # modify history_command -rp param and -sn param for option_tuple in self._get_to_be_replaced_option(parser): history_command = self._replace_history_option( - history_command, (input_options, options), option_tuple) + history_command, (input_options, argument.options), option_tuple) # add history command to Scheduler.command_queue LOG.info("Retry command: %s", history_command) Scheduler.command_queue[-1] = history_command - return options + return argument.options @classmethod def _process_command_help(cls, parser, para_list): @@ -577,8 +578,9 @@ class Console(object): if not params: raise ParamError("no retry case exists") session_id, command, report_path, failed_list = \ - params[0], params[1], params[2], \ - [(module, failed) for module, case_list in params[3].items() + params[ReportConst.session_id], params[ReportConst.command], \ + params[ReportConst.report_path], \ + [(module, failed) for module, case_list in params[ReportConst.unsuccessful_params].items() for failed in case_list] if Scheduler.mode == ModeType.decc: from xdevice import SuiteReporter @@ -662,7 +664,7 @@ class Console(object): options.session else "'%s' has no command executed" % \ options.session raise ParamError(error_msg) - history_command, history_report_path = params[1], params[2] + history_command, history_report_path = params[ReportConst.command], params[ReportConst.report_path] else: history_command, history_report_path = "", "" for command_tuple in Scheduler.command_queue[:-1]: diff --git a/src/xdevice/_core/constants.py b/src/xdevice/_core/constants.py index a65b66f..2c2f620 100644 --- a/src/xdevice/_core/constants.py +++ b/src/xdevice/_core/constants.py @@ -141,6 +141,7 @@ class HostDrivenTestType(object): """ device_test = "DeviceTest" windows_test = "WindowsTest" + app_test = "AppTest" TEST_DRIVER_SET = { @@ -278,6 +279,15 @@ class ConfigConst(object): device_log = "device_log" +@dataclass +class ReportConst(object): + session_id = "session_id" + command = "command" + report_path = "report_path" + unsuccessful_params = "unsuccessful_params" + data_reports = "data_reports" + + class FilePermission(object): mode_777 = 0o777 mode_755 = 0o755 @@ -287,3 +297,4 @@ class FilePermission(object): @dataclass class DeviceConnectorType: hdc = "usb-hdc" + diff --git a/src/xdevice/_core/executor/concurrent.py b/src/xdevice/_core/executor/concurrent.py index a8c7d8e..a3214ed 100644 --- a/src/xdevice/_core/executor/concurrent.py +++ b/src/xdevice/_core/executor/concurrent.py @@ -26,6 +26,7 @@ from concurrent.futures import wait from _core.constants import ModeType from _core.constants import ConfigConst +from _core.constants import ReportConst from _core.executor.request import Request from _core.logger import platform_logger from _core.plugin import Config @@ -269,11 +270,11 @@ class DriversThread(threading.Thread): for i in Handler.DAV.case_id_list: failed_list.append(i + "#" + i) else: - failed_list = params[3].get(module_name, []) + failed_list = params[ReportConst.unsuccessful_params].get(module_name, []) except: - failed_list = params[3].get(module_name, []) + failed_list = params[ReportConst.unsuccessful_params].get(module_name, []) if not failed_list: - failed_list = params[3].get(str(module_name).split(".")[0], []) + failed_list = params[ReportConst.unsuccessful_params].get(str(module_name).split(".")[0], []) unpassed_test_params.extend(failed_list) LOG.debug("Get unpassed test params %s", unpassed_test_params) return unpassed_test_params @@ -432,7 +433,7 @@ class DriversThread(threading.Thread): from _core.report.result_reporter import ResultReporter params = ResultReporter.get_task_info_params(history_report_path) if params: - report_data_dict = dict(params[4]) + report_data_dict = dict(params[ReportConst.report_path]) if execute_result_name in report_data_dict.keys(): return report_data_dict.get(execute_result_name) elif execute_result_name.split(".")[0] in \ diff --git a/src/xdevice/_core/executor/scheduler.py b/src/xdevice/_core/executor/scheduler.py index 4d91600..d1e294b 100644 --- a/src/xdevice/_core/executor/scheduler.py +++ b/src/xdevice/_core/executor/scheduler.py @@ -57,6 +57,7 @@ from _core.constants import DeviceLabelType from _core.constants import SchedulerType from _core.constants import ListenerType from _core.constants import ConfigConst +from _core.constants import ReportConst from _core.constants import HostDrivenTestType from _core.executor.concurrent import DriversThread from _core.executor.concurrent import QueueMonitorThread @@ -1149,10 +1150,10 @@ class Scheduler(object): history_report_path = \ getattr(task.config, ConfigConst.history_report_path, "") params = ResultReporter.get_task_info_params(history_report_path) - if params and params[3]: - if dict(params[3]).get(module_name, []): + if params and params[ReportConst.unsuccessful_params]: + if dict(params[ReportConst.unsuccessful_params]).get(module_name, []): failed_flag = True - elif dict(params[3]).get(str(module_name).split(".")[0], []): + elif dict(params[ReportConst.unsuccessful_params]).get(str(module_name).split(".")[0], []): failed_flag = True return failed_flag diff --git a/src/xdevice/_core/logger.py b/src/xdevice/_core/logger.py index ab8068f..c14cf29 100644 --- a/src/xdevice/_core/logger.py +++ b/src/xdevice/_core/logger.py @@ -19,6 +19,7 @@ import logging import sys import time +import threading from logging.handlers import RotatingFileHandler from _core.constants import LogType @@ -325,7 +326,8 @@ def remove_encrypt_file_handler(): def _init_global_logger(name=None): handler = logging.StreamHandler(sys.stdout) - log_format = "[%(asctime)s] [%(name)s] [%(levelname)s] [%(message)s]" + log_format = \ + "[%(asctime)s] [%(thread)d] [%(name)s] [%(levelname)s] [%(message)s]" handler.setFormatter(logging.Formatter(log_format)) log = FrameworkLog(name) log.platform_log.setLevel(logging.INFO) @@ -398,7 +400,7 @@ class EncryptFileHandler(RotatingFileHandler): stream = getattr(self, "stream", self._open()) stream.write(msg) self.flush() - except RecursionError as _: + except RecursionError as _: # pylint:disable=undefined-variable raise def _encrypt_valid(self): @@ -423,15 +425,17 @@ class EncryptFileHandler(RotatingFileHandler): msg = record.msg if msg and "%s" in msg: msg = msg % record.args - info = "[%s] [%s] [%s] %s%s" \ - % (create_time, name, level_name, msg, "\n") + info = "[%s] [%s] [%s] [%s] %s%s" \ + % (create_time, threading.currentThread().ident, name, + level_name, msg, "\n") try: return do_rsa_encrypt(info) except ParamError as error: error_no_str = \ "ErrorNo={}".format(getattr(error, "error_no", "00113")) - info = "[%s] [%s] [%s] [%s] [%s]\n" % ( - create_time, name, "ERROR", error, error_no_str) + info = "[%s] [%s] [%s] [%s] [%s] [%s]\n" % ( + create_time, threading.currentThread().ident, + name, "ERROR", error, error_no_str) self.encrypt_error = bytes(info, "utf-8") return self.encrypt_error diff --git a/src/xdevice/_core/report/__main__.py b/src/xdevice/_core/report/__main__.py index 724d02f..d6a6b65 100644 --- a/src/xdevice/_core/report/__main__.py +++ b/src/xdevice/_core/report/__main__.py @@ -24,14 +24,13 @@ from _core.logger import platform_logger from _core.report.reporter_helper import ExecInfo from _core.report.reporter_helper import ReportConstant from _core.report.result_reporter import ResultReporter +from _core.utils import is_python_satisfied LOG = platform_logger("ReportMain") def main_report(): - if sys.version < '3.7': - LOG.error("Please use python 3.7 or higher version to start " - "project") + if not is_python_satisfied(): return args = sys.argv diff --git a/src/xdevice/_core/report/result_reporter.py b/src/xdevice/_core/report/result_reporter.py index 8cfe966..53b6be6 100755 --- a/src/xdevice/_core/report/result_reporter.py +++ b/src/xdevice/_core/report/result_reporter.py @@ -130,16 +130,6 @@ class ResultReporter(IReporter): self.set_summary_report_result( self.summary_data_path, DataHelper.to_string(test_suites_element)) - if self._check_mode(ModeType.decc): - try: - from agent.decc import Handler - from xdevice import Scheduler - LOG.info("Upload task summary result to decc") - Handler.upload_task_summary_results( - self.get_result_of_summary_report()) - except ModuleNotFoundError as error: - LOG.error("Module not found %s", error.args) - def _update_test_suites(self, test_suites_element): # initial attributes for test suites element test_suites_attributes, need_update_attributes = \ @@ -630,8 +620,7 @@ class ResultReporter(IReporter): LOG.error("%s error!", ReportConstant.task_info_record) return () - return result["session_id"], result["command"], result["report_path"],\ - result["unsuccessful_params"], result["data_reports"] + return result @classmethod def set_summary_report_result(cls, summary_data_path, result_xml): diff --git a/src/xdevice/_core/utils.py b/src/xdevice/_core/utils.py index 0d62564..60f3037 100644 --- a/src/xdevice/_core/utils.py +++ b/src/xdevice/_core/utils.py @@ -19,6 +19,7 @@ import copy import os import socket +import sys import time import platform import argparse @@ -94,7 +95,7 @@ def stop_standing_subprocess(process): signal_value = signal.SIGINT if sys_type == "Windows" \ else signal.SIGTERM os.kill(process.pid, signal_value) - except (PermissionError, AttributeError, FileNotFoundError, + except (PermissionError, AttributeError, FileNotFoundError, # pylint:disable=undefined-variable SystemError) as error: LOG.error("Stop standing subprocess error '%s'" % error) @@ -202,7 +203,7 @@ def exec_cmd(cmd, timeout=5 * 60, error_print=True, join_result=False, redirect= else: return err if err else out - except (TimeoutError, KeyboardInterrupt, AttributeError, ValueError, + except (TimeoutError, KeyboardInterrupt, AttributeError, ValueError, # pylint:disable=undefined-variable EOFError, IOError) as _: sys_type = platform.system() if sys_type == "Linux" or sys_type == "Darwin": @@ -454,6 +455,14 @@ def is_config_str(content): return True if "{" in content and "}" in content else False +def is_python_satisfied(): + mini_version = (3, 7, 0) + if sys.version_info > mini_version: + return True + LOG.error("Please use python {} or higher version to start project".format(mini_version)) + return False + + def get_version(): from xdevice import Variables ver = '' diff --git a/src/xdevice/variables.py b/src/xdevice/variables.py index 42fba1c..4242fe0 100644 --- a/src/xdevice/variables.py +++ b/src/xdevice/variables.py @@ -66,8 +66,8 @@ def _init_global_config(): # set report variables Variables.report_vars.log_dir = "log" Variables.report_vars.report_dir = "reports" - Variables.report_vars.log_format = "[%(asctime)s] [%(name)s] " \ - "[%(levelname)s] %(message)s" + Variables.report_vars.log_format = \ + "[%(asctime)s] [%(thread)d] [%(name)s] [%(levelname)s] %(message)s" Variables.report_vars.log_level = logging.INFO Variables.report_vars.log_handler = "console, file"