#!/usr/bin/env python3 # coding=utf-8 # # Copyright (c) 2020-2022 Huawei Device Co., Ltd. # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # import argparse import json import os import platform import re 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 from _core.error import ErrorMessage from _core.exception import ParamError from _core.exception import ExecuteTerminate from _core.executor.request import Task from _core.logger import platform_logger from _core.plugin import Plugin from _core.plugin import get_plugin from _core.utils import convert_mac from _core.utils import SplicingAction from _core.utils import is_python_satisfied from _core.report.result_reporter import ResultReporter from _core.context.center import Context from _core.context.upload import Uploader from _core.variables import Variables __all__ = ["Console"] LOG = platform_logger("Console") try: if platform.system() != 'Windows': import readline except 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): """ Class representing a console for executing test. Main xDevice console providing user with the interface to interact """ __instance = None def __new__(cls, *args, **kwargs): """ Singleton instance """ if cls.__instance is None: cls.__instance = super(Console, cls).__new__(cls, *args, **kwargs) return cls.__instance def __init__(self): pass @classmethod def handler_terminate_signal(cls, signalnum, frame): # ctrl+c del signalnum, frame if not Context.is_executing(): return Context.set_execute_status(False) LOG.info("Get terminate input") if Context.terminate_cmd_exec(): terminate_thread = threading.Thread( target=Context.terminate_cmd_exec()) terminate_thread.daemon = True terminate_thread.start() def console(self, args): """ Main xDevice console providing user with the interface to interact """ if not is_python_satisfied(): sys.exit(0) if args is None or len(args) < 2: # init environment manager Context.set_execute_status(True) EnvironmentManager() # Enter xDevice console self._console() else: # init environment manager Context.set_execute_status(True) EnvironmentManager() # Enter xDevice command parser self.command_parser(" ".join(args[1:])) def _console(self): # Enter xDevice console signal.signal(signal.SIGINT, self.handler_terminate_signal) while True: try: usr_input = input(">>> ") if usr_input == "": continue self.command_parser(usr_input) except SystemExit as _: LOG.info("Program exit normally!") break except ExecuteTerminate as _: LOG.info("Execution terminated") except (IOError, EOFError, KeyboardInterrupt) as error: LOG.exception("Input Error: {}".format(error), exc_info=False) def argument_parser(self, para_list): """ Argument parser """ options = None unparsed = [] valid_param = True parser = None try: parser = argparse.ArgumentParser( description="Specify tests to run.") group = parser.add_mutually_exclusive_group() parser.add_argument("action", type=str.lower, help="Specify action") parser.add_argument("task", type=str, default=None, help="Specify task name") group.add_argument("-l", "--testlist", action=SplicingAction, type=str, nargs='+', dest=ConfigConst.testlist, default="", help="Specify test list" ) group.add_argument("-tf", "--testfile", action=SplicingAction, type=str, nargs='+', dest=ConfigConst.testfile, default="", help="Specify test list file" ) parser.add_argument("-tc", "--testcase", action="store", type=str, dest=ConfigConst.testcase, default="", help="Specify test case" ) parser.add_argument("-c", "--config", action=SplicingAction, type=str, nargs='+', dest=ConfigConst.configfile, default="", help="Specify config file path" ) parser.add_argument("-sn", "--device_sn", action="store", type=str, dest=ConfigConst.device_sn, default="", help="Specify device serial number" ) parser.add_argument("-rp", "--reportpath", action=SplicingAction, type=str, nargs='+', dest=ConfigConst.report_path, default="", help="Specify test report path" ) parser.add_argument("-respath", "--resourcepath", action=SplicingAction, type=str, nargs='+', dest=ConfigConst.resource_path, default="", help="Specify test resource path" ) parser.add_argument("-tcpath", "--testcasespath", action=SplicingAction, type=str, nargs='+', dest=ConfigConst.testcases_path, default="", help="Specify testcases path" ) parser.add_argument("-ta", "--testargs", action=SplicingAction, type=str, nargs='+', dest=ConfigConst.testargs, default={}, help="Specify test arguments" ) parser.add_argument("-pt", "--passthrough", action="store_true", dest=ConfigConst.pass_through, help="Pass through test arguments" ) parser.add_argument("-env", "--environment", action=SplicingAction, type=str, nargs='+', dest=ConfigConst.test_environment, default="", help="Specify test environment" ) parser.add_argument("-e", "--exectype", action="store", type=str, dest=ConfigConst.exectype, default="device", help="Specify test execute type" ) parser.add_argument("-t", "--testtype", nargs='*', dest=ConfigConst.testtype, default=[], help="Specify test type" + "(UT,MST,ST,PERF,SEC,RELI,DST,ALL)" ) parser.add_argument("-td", "--testdriver", action="store", type=str, dest=ConfigConst.testdriver, default="", help="Specify test driver id" ) parser.add_argument("-tl", "--testlevel", action="store", type=str, dest="testlevel", default="", help="Specify test level" ) parser.add_argument("-bv", "--build_variant", action="store", type=str, dest="build_variant", default="release", help="Specify build variant(release,debug)" ) parser.add_argument("-cov", "--coverage", action="store", type=str, dest="coverage", default="", help="Specify coverage" ) parser.add_argument("--retry", action="store", type=str, dest=ConfigConst.retry, default="", help="Specify retry command" ) parser.add_argument("--session", action=SplicingAction, type=str, nargs='+', dest=ConfigConst.session, help="retry task by session id") parser.add_argument("--dryrun", action="store_true", dest=ConfigConst.dry_run, help="show retry test case list") parser.add_argument("--reboot-per-module", action="store_true", dest=ConfigConst.reboot_per_module, help="reboot devices before executing each " "module") parser.add_argument("--check-device", action="store_true", dest=ConfigConst.check_device, help="check the test device meets the " "requirements") parser.add_argument("--repeat", type=int, default=1, dest=ConfigConst.repeat, help="number of times that a task is executed" " repeatedly") parser.add_argument("-le", "--local_execution_log_path", dest="local_execution_log_path", help="- The local execution log path.") parser.add_argument("-s", "--subsystem", dest="subsystems", action="store", type=str, help="- Specify the list of subsystem") parser.add_argument("-p", "--part", dest="parts", action="store", type=str, help="- Specify the list of part") parser.add_argument("-di", "--device_info", dest=ConfigConst.device_info, action="store", type=str, help="- describe device info in json style") parser.add_argument("-kim", "--kits_in_module", dest=ConfigConst.kits_in_module, action=SplicingAction, type=str, nargs='+', default="", help="- kits that are used for specify module") parser.add_argument("--kp", "--kits_params", dest=ConfigConst.kits_params, action=SplicingAction, type=str, nargs='+', default="", help='- the params of kits that related to' ' module' ) parser.add_argument("--auto_retry", dest=ConfigConst.auto_retry, type=int, default=0, help="- the count of auto retry") parser.add_argument("--enable_unicode", dest=ConfigConst.enable_unicode, action="store_true", help="enable unicode about test args." "It must be used with and immediately " "following the -ta or --testargs parameter") parser.add_argument("-module_config", action=SplicingAction, type=str, nargs='+', dest=ConfigConst.module_config, default="", help="Specify module config json path"), parser.add_argument("--scheduler", dest=ConfigConst.scheduler, action="store", type=str, default="default", help="Select different scheduling schemes." "--scheduler module") self._params_pre_processing(para_list) (options, unparsed) = parser.parse_known_args(para_list) if unparsed: LOG.warning("Unparsed input: %s", " ".join(unparsed)) self._params_post_processing(options) except SystemExit as _: valid_param = False parser.print_help() LOG.warning("Parameter parsing system exit exception.") return Argument(options, unparsed, valid_param, parser) @classmethod def _params_pre_processing(cls, para_list): if len(para_list) <= 1 or ( len(para_list) > 1 and "-" in str(para_list[1])): para_list.insert(1, Task.EMPTY_TASK) for index, param in enumerate(para_list): if param == "--retry": if index + 1 == len(para_list): para_list.append("retry_previous_command") elif "-" in str(para_list[index + 1]): para_list.insert(index + 1, "retry_previous_command") elif param == "-->": para_list[index] = "!%s" % param def _params_post_processing(self, options): # 重新初始化对象,无需重新进入命令交互窗口,可以使用最新的配置信息 Variables.config = UserConfigManager() if options.config: Variables.config = UserConfigManager(config_file=options.config) if options.test_environment: Variables.config = UserConfigManager(env=options.test_environment) self._update_task_args(options) # params post-processing if options.task == Task.EMPTY_TASK: setattr(options, ConfigConst.task, "") if options.testargs: if options.enable_unicode: test_args = str(options.testargs).encode("utf-8").decode('unicode_escape') setattr(options, ConfigConst.testargs, test_args) if not options.pass_through: test_args = self._parse_combination_param(options.testargs) setattr(options, ConfigConst.testargs, test_args) else: setattr(options, ConfigConst.testargs, { ConfigConst.pass_through: options.testargs}) if not options.resource_path: setattr(options, ConfigConst.resource_path, Variables.config.get_resource_path()) if not options.testcases_path: setattr(options, ConfigConst.testcases_path, Variables.config.get_testcases_dir()) setattr(options, ConfigConst.device_log, Variables.config.devicelog) if options.subsystems: subsystem_list = str(options.subsystems).split(";") setattr(options, ConfigConst.subsystems, subsystem_list) if options.parts: part_list = str(options.parts).split(";") setattr(options, ConfigConst.parts, part_list) if options.device_info: device_info = self._parse_extension_device_info(str(options.device_info)) setattr(options, ConfigConst.device_info, device_info) if options.kits_in_module: kit_list = str(options.kits_in_module).split(";") setattr(options, ConfigConst.kits_in_module, kit_list) params = getattr(options, ConfigConst.kits_params, "") setattr(options, ConfigConst.kits_params, self._parse_kit_params(params)) def command_parser(self, args): try: Context.command_queue().append(args) LOG.info("Input command: {}".format(convert_mac(args))) args = self._pre_handle_test_args(args) para_list = args.split() argument = self.argument_parser(para_list) options = argument.options if options is None or not argument.valid_param: LOG.warning("Options is None.") return if options.action == ToolCommandType.toolcmd_key_run and \ options.retry: if hasattr(options, ConfigConst.auto_retry): setattr(options, ConfigConst.auto_retry, 0) options = self._get_retry_options(options, argument.parser) if options.dry_run: history_report_path = getattr(options, "history_report_path", "") self._list_retry_case(history_report_path) return else: from xdevice import SuiteReporter SuiteReporter.clear_failed_case_list() SuiteReporter.clear_report_result() command = options.action if command == "": LOG.info("Command is empty.") return self._process_command(command, options, para_list, argument.parser) except (ParamError, ValueError, TypeError, SyntaxError, AttributeError) as exception: LOG.exception(exception, exc_info=False) Uploader.upload_unavailable_result(str(exception.args)) Uploader.upload_report_end() finally: if isinstance(Context.command_queue().get(-1), str): Context.command_queue().pop() def _process_command(self, command, options, para_list, parser): if command.startswith(ToolCommandType.toolcmd_key_help): self._process_command_help(parser, para_list) elif command.startswith(ToolCommandType.toolcmd_key_show): self._process_command_show(para_list) elif command.startswith(ToolCommandType.toolcmd_key_run): self._process_command_run(command, options) elif command.startswith(ToolCommandType.toolcmd_key_quit): self._process_command_quit(command) elif command.startswith(ToolCommandType.toolcmd_key_list): self._process_command_list(command, para_list) elif command.startswith(ToolCommandType.toolcmd_key_tool): self._process_command_tool(command, para_list, options) else: LOG.error("Unsupported command action", error_no="00100", action=command) def _get_retry_options(self, options, parser): input_options = copy.deepcopy(options) # get history command, history report path history_command, history_report_path = self._parse_retry_option( options) LOG.info("History command: %s", history_command) if not os.path.exists(history_report_path) and \ Context.session().mode != ModeType.decc: raise ParamError(ErrorMessage.Common.Code_0101005.format(history_report_path)) # parse history command, set history report path is_dry_run = True if options.dry_run else False history_command = self._wash_history_command(history_command) history_command_inner = self._pre_handle_test_args(history_command) argument = self.argument_parser(history_command_inner.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, argument.options), option_tuple) # add history command to command_queue LOG.info("Retry command: %s", history_command) Context.command_queue().update(-1, history_command) return argument.options @classmethod def _process_command_help(cls, parser, para_list): if para_list[0] == ToolCommandType.toolcmd_key_help: if len(para_list) == 2: cls.display_help_command_info(para_list[1]) else: parser.print_help() else: LOG.error("Wrong help command. Use 'help' to print help") return @classmethod def _process_command_show(cls, para_list): if para_list[0] == ToolCommandType.toolcmd_key_show: pass else: LOG.error("Wrong show command.") return @classmethod def _process_command_run(cls, command, options): scheduler = get_plugin(plugin_type=Plugin.SCHEDULER, plugin_id=SchedulerType.scheduler)[0] if scheduler is None: LOG.error("Can not find the scheduler plugin.") else: scheduler.exec_command(command, options) return def _process_command_list(self, command, para_list): if command != ToolCommandType.toolcmd_key_list: LOG.error("Wrong list command.") return if len(para_list) > 1: if para_list[1] == "history": self._list_history() elif para_list[1] == "devices" or para_list[1] == Task.EMPTY_TASK: env_manager = EnvironmentManager() env_manager.list_devices() else: self._list_task_id(para_list[1]) return # list devices env_manager = EnvironmentManager() env_manager.list_devices() return @classmethod def _process_command_quit(cls, command): if command == ToolCommandType.toolcmd_key_quit: env_manager = EnvironmentManager() env_manager.env_stop() sys.exit(0) else: LOG.error("Wrong exit command. Use 'quit' to quit program") return @classmethod def _process_command_tool(cls, command, para_list, options): if not command.startswith(ToolCommandType.toolcmd_key_tool): LOG.error("Wrong tool command.") return if len(para_list) > 2: tool_name = para_list[1] if tool_name in [ConfigConst.renew_report, ConfigConst.export_report]: report_path = str(getattr(options, ConfigConst.report_path, "")) if not report_path: LOG.error("report path must be specified, you can pass it with option -rp ") return cls._report_helper(report_path.split(";"), tool_name) @staticmethod def _parse_combination_param(combination_value): # sample: size:xxx1;exclude-annotation:xxx parse_result = {} key_value_pairs = str(combination_value).split(";") for key_value_pair in key_value_pairs: key, value = key_value_pair.split(":", 1) if not value: raise ParamError(ErrorMessage.Common.Code_0101006.format(value)) if ConfigConst.pass_through not in key: value_list = str(value).split(",") exist_list = parse_result.get(key, []) exist_list.extend(value_list) parse_result[key] = exist_list else: parse_result[key] = value return parse_result @staticmethod def _parse_extension_device_info(device_info_str): parse_result = json.loads(device_info_str).get("devices", None) if isinstance(parse_result, list): parse_result = [x for x in parse_result if 'sn' in x and 'type' in x] else: parse_result = None return parse_result @staticmethod def _update_task_args(options): args = {} repeat = options.repeat # 命令行repeat设值大于1时,才更新 if repeat > 1: args.update({ConfigConst.repeat: repeat}) if options.testargs and not options.pass_through: for combine_value in options.testargs.split(";"): arg = combine_value.split(":", 1) args.update({arg[0].strip(): arg[1].strip()}) Variables.config.update_task_args(new_args=args) @classmethod def _list_history(cls): print("Command history:") print("{0:<16}{1:<50}{2:<50}".format( "TaskId", "Command", "ReportPath")) for command_info in Context.command_queue().list_history(): command, report_path = command_info[1], command_info[2] if len(command) > MAX_VISIBLE_LENGTH: command = "%s..." % command[:MAX_RESERVED_LENGTH] if len(report_path) > MAX_VISIBLE_LENGTH: report_path = "%s..." % report_path[:MAX_RESERVED_LENGTH] print("{0:<16}{1:<50}{2:<50}".format( command_info[0], command, report_path)) @classmethod def _list_task_id(cls, task_id): print("List task:") task_id, command, report_path = task_id, "", "" for command_info in Context.command_queue().list_history(): if command_info[0] != task_id: continue task_id, command, report_path = command_info break print("{0:<16}{1:<100}".format("TaskId:", task_id)) print("{0:<16}{1:<100}".format("Command:", command)) print("{0:<16}{1:<100}".format("ReportPath:", report_path)) @classmethod def _list_retry_case(cls, history_path): params = ResultReporter.get_task_info_params(history_path) if not params: raise ParamError(ErrorMessage.Common.Code_0101007) session_id, command, report_path, failed_list = \ 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 Context.session().mode == ModeType.decc: from xdevice import SuiteReporter SuiteReporter.failed_case_list = failed_list return # draw tables in console left, middle, right = 23, 49, 49 two_segments = "{0:-<%s}{1:-<%s}+" % (left, middle + right) two_rows = "|{0:^%s}|{1:^%s}|" % (left - 1, middle + right - 1) three_segments = "{0:-<%s}{1:-<%s}{2:-<%s}+" % (left, middle, right) three_rows = "|{0:^%s}|{1:^%s}|{2:^%s}|" % \ (left - 1, middle - 1, right - 1) if len(session_id) > middle + right - 1: session_id = "%s..." % session_id[:middle + right - 4] if len(command) > middle + right - 1: command = "%s..." % command[:middle + right - 4] if len(report_path) > middle + right - 1: report_path = "%s..." % report_path[:middle + right - 4] print(two_segments.format("+", '+')) print(two_rows.format("SessionId", session_id)) print(two_rows.format("Command", command)) print(two_rows.format("ReportPath", report_path)) print(three_segments.format("+", '+', '+')) print(three_rows.format("Module", "Testsuite", "Testcase")) print(three_segments.format("+", '+', '+')) for module, failed in failed_list: # all module is failed if "#" not in failed: class_name = "-" test = "-" # others, get failed cases info else: pos = failed.rfind("#") class_name = failed[:pos] test = failed[pos + 1:] if len(module) > left - 1: module = "%s..." % module[:left - 4] if len(class_name) > middle - 1: class_name = "%s..." % class_name[:middle - 4] if len(test) > right - 1: test = "%s..." % test[:right - 4] print(three_rows.format(module, class_name, test)) print(three_segments.format("+", '+', '+')) @classmethod def _find_history_path(cls, session): if os.path.isdir(session): return session target_path = os.path.join( Variables.exec_dir, Variables.report_vars.report_dir, session) if not os.path.isdir(target_path): raise ParamError(ErrorMessage.Common.Code_0101008.format(session)) return target_path def _parse_retry_option(self, options): if Context.session().mode == ModeType.decc: if Context.command_queue().size() < 2: raise ParamError(ErrorMessage.Common.Code_0101009) _, history_command, history_report_path = \ Context.command_queue().get(-2) return history_command, history_report_path # get history_command, history_report_path if options.retry == "retry_previous_command": history_path = os.path.join(Variables.temp_dir, "latest") if options.session: history_path = self._find_history_path(options.session) params = ResultReporter.get_task_info_params(history_path) if not params: error_msg = ErrorMessage.Common.Code_0101009 if not options.session \ else ErrorMessage.Common.Code_0101010.format(options.session) raise ParamError(error_msg) history_command, history_report_path = params[ReportConst.command], params[ReportConst.report_path] else: history_command, history_report_path = "", "" for command_tuple in Context.command_queue().list_history(): if command_tuple[0] != options.retry: continue history_command, history_report_path = \ command_tuple[1], command_tuple[2] break if not history_command: raise ParamError(ErrorMessage.Common.Code_0101011.format(options.retry)) return history_command, history_report_path @classmethod def display_help_command_info(cls, command): if command == ToolCommandType.toolcmd_key_run: print(RUN_INFORMATION) elif command == ToolCommandType.toolcmd_key_list: print(LIST_INFORMATION) elif command == "empty": print(GUIDE_INFORMATION) else: print("'%s' command no help information." % command) @classmethod def _replace_history_option(cls, history_command, options_tuple, target_option_tuple): input_options, history_options = options_tuple option_name, short_option_str, full_option_str = target_option_tuple history_value = getattr(history_options, option_name, "") input_value = getattr(input_options, option_name, "") if history_value: if input_value: history_command = history_command.replace(history_value, input_value) setattr(history_options, option_name, input_value) else: history_command = str(history_command).replace( history_value, "").replace(full_option_str, ""). \ replace(short_option_str, "") else: if input_value: history_command = "{}{}".format( history_command, " %s %s" % (short_option_str, input_value)) setattr(history_options, option_name, input_value) return history_command.strip() @classmethod def _get_to_be_replaced_option(cls, parser): name_list = ["report_path", "device_sn"] option_str_list = list() action_list = getattr(parser, "_actions", []) if action_list: for action in action_list: if action.dest not in name_list: continue option_str_list.append((action.dest, action.option_strings[0], action.option_strings[1])) else: option_str_list = [("report_path", "-rp", "--reportpath"), ("device_sn", "-sn", "--device_sn")] return option_str_list @classmethod def _report_helper(cls, report_list, tool_name): from _core.report.__main__ import main_report, export_report for report in report_list: run_command = Context.command_queue().pop() Context.command_queue().append(("", run_command, report)) sys.argv.insert(1, report) if tool_name == ConfigConst.renew_report: main_report() elif tool_name == ConfigConst.export_report: export_report() sys.argv.pop(1) @classmethod def _parse_kit_params(cls, kits_params): params_result = dict() if not kits_params: return params_result kits_params_list = str(kits_params).split(" ") if len(kits_params_list) % 2 != 0: LOG.warning("Unavailable kit params") else: for index in range(0, len(kits_params_list), 2): params_result.update( {kits_params_list[index]: kits_params_list[index + 1]}) return params_result @classmethod def _wash_history_command(cls, history_command): # clear redundant content in history command. e.g. repeat,sn if "--repeat" in history_command or "-sn" in history_command \ or "--auto_retry" in history_command: split_list = list(history_command.split()) if "--repeat" in split_list: pos = split_list.index("--repeat") split_list = split_list[:pos] + split_list[pos + 2:] if "-sn" in split_list: pos = split_list.index("-sn") split_list = split_list[:pos] + split_list[pos + 2:] if "--auto_retry" in split_list: pos = split_list.index("--auto_retry") split_list = split_list[:pos] + split_list[pos + 2:] return " ".join(split_list) else: return history_command @classmethod def _pre_handle_test_args(cls, args): res = re.match(".+(?:-ta|--testargs)\\s+(.+)\\s+--enable_unicode", args, re.S) if not res: return args unicode = ''.join(rf'\u{ord(x):04x}' for x in res.group(1)) args = args[:res.start(1)] + unicode + args[res.end(1):] return args RUN_INFORMATION = """run: This command is used to execute the selected testcases. It includes a series of processes such as use case compilation, \ execution, and result collection. usage: run [-l TESTLIST [TESTLIST ...] | -tf TESTFILE [TESTFILE ...]] [-tc TESTCASE] [-c CONFIG] [-sn DEVICE_SN] [-rp REPORT_PATH [REPORT_PATH ...]] [-respath RESOURCE_PATH [RESOURCE_PATH ...]] [-tcpath TESTCASES_PATH [TESTCASES_PATH ...]] [-ta TESTARGS [TESTARGS ...]] [-pt] [-env TEST_ENVIRONMENT [TEST_ENVIRONMENT ...]] [-e EXECTYPE] [-t [TESTTYPE [TESTTYPE ...]]] [-td TESTDRIVER] [-tl TESTLEVEL] [-bv BUILD_VARIANT] [-cov COVERAGE] [--retry RETRY] [--session SESSION] [--dryrun] [--reboot-per-module] [--check-device] [--repeat REPEAT] [--scheduler SCHEDULER] action task Specify tests to run. positional arguments: action Specify action task Specify task name,such as "ssts", "acts", "hits" optional arguments: -h, --help show this help message and exit -l TESTLIST [TESTLIST ...], --testlist TESTLIST [TESTLIST ...] Specify test list -tf TESTFILE [TESTFILE ...], --testfile TESTFILE [TESTFILE ...] Specify test list file -tc TESTCASE, --testcase TESTCASE Specify test case -c CONFIG, --config CONFIG Specify config file path -sn DEVICE_SN, --device_sn DEVICE_SN Specify device serial number -rp REPORT_PATH [REPORT_PATH ...], --reportpath REPORT_PATH [REPORT_PATH \ ...] Specify test report path -respath RESOURCE_PATH [RESOURCE_PATH ...], --resourcepath RESOURCE_PATH \ [RESOURCE_PATH ...] Specify test resource path -tcpath TESTCASES_PATH [TESTCASES_PATH ...], --testcasespath \ TESTCASES_PATH [TESTCASES_PATH ...] Specify testcases path -ta TESTARGS [TESTARGS ...], --testargs TESTARGS [TESTARGS ...] Specify test arguments -pt, --passthrough Pass through test arguments -env TEST_ENVIRONMENT [TEST_ENVIRONMENT ...], --environment \ TEST_ENVIRONMENT [TEST_ENVIRONMENT ...] Specify test environment -e EXECTYPE, --exectype EXECTYPE Specify test execute type -t [TESTTYPE [TESTTYPE ...]], --testtype [TESTTYPE [TESTTYPE ...]] Specify test type(UT,MST,ST,PERF,SEC,RELI,DST,ALL) -td TESTDRIVER, --testdriver TESTDRIVER Specify test driver id -tl TESTLEVEL, --testlevel TESTLEVEL Specify test level -bv BUILD_VARIANT, --build_variant BUILD_VARIANT Specify build variant(release,debug) -cov COVERAGE, --coverage COVERAGE Specify coverage --retry RETRY Specify retry command --session SESSION retry task by session id --dryrun show retry test case list --reboot-per-module reboot devices before executing each module --check-device check the test device meets the requirements --repeat REPEAT number of times that a task is executed repeatedly --scheduler SCHEDULER Select different scheduling schemes Examples: run -l ; run -tf test/resource/.txt run –l -sn ; run –l -respath run –l -ta size:large run –l –ta class:## run –l -ta size:large -pt run –l –env run –l –e device run –l –t ALL run –l –td CppTest run –l -tcpath resource/testcases run ssts run ssts –tc ; run ssts -sn ; run ssts -respath ... ... run acts run acts –tc ; run acts -sn ; run acts -respath ... ... run hits ... ... run --retry run --retry --session run --retry --dryrun """ LIST_INFORMATION = "list:" + """ This command is used to display device list and task record.\n usage: list list history list Introduction: list: display device list list history: display history record of a serial of tasks list : display history record about task what contains specific id Examples: list list history list 6e****90 """ GUIDE_INFORMATION = """help: use help to get information. usage: run: Display a list of supported run command. list: Display a list of supported device and task record. Examples: help run help list """