import argparse
import json
import os
import platform
import re
import signal
import sys
import threading
import copy
import time
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:
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):
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:
if Variables.config.enable_cluster():
from _core.cluster.__main__ import cluster_main
cluster_main()
time.sleep(1)
Context.set_execute_status(True)
EnvironmentManager()
self._console()
else:
Context.set_execute_status(True)
cmd_args = " ".join(args[1:])
para_list = self._pre_handle_test_args(cmd_args).split()
argument = self.argument_parser(para_list)
options = argument.options
config_file = options.config
test_environment = options.test_environment
if config_file or test_environment:
EnvironmentManager(environment=test_environment, user_config_file=config_file)
else:
EnvironmentManager()
self.command_parser(cmd_args)
def _console(self):
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.")
parser.add_argument(
"action",
type=str.lower,
help="Specify action"
)
parser.add_argument(
"task",
type=str,
default=None,
help="Specify task name"
)
group1 = parser.add_mutually_exclusive_group()
group1.add_argument(
"-l", "--testlist",
action=SplicingAction,
type=str,
nargs='+',
dest=ConfigConst.testlist,
default="",
help="Specify test list"
)
group1.add_argument(
"-tc", "--testcase",
action="store",
type=str,
dest=ConfigConst.testcase,
default="",
help="Specify test case"
)
group1.add_argument(
"-tf", "--testfile",
action=SplicingAction,
type=str,
nargs='+',
dest=ConfigConst.testfile,
default="",
help="Specify test list file"
)
group2 = parser.add_mutually_exclusive_group()
group2.add_argument(
"-c", "--config",
action=SplicingAction,
type=str,
nargs='+',
dest=ConfigConst.configfile,
default="",
help="Specify config file path"
)
group2.add_argument(
"-env", "--environment",
action=SplicingAction,
type=str,
nargs='+',
dest=ConfigConst.test_environment,
default="",
help="Specify test environment"
)
group3 = parser.add_mutually_exclusive_group()
group3.add_argument(
"--repeat",
type=int,
default=1,
dest=ConfigConst.repeat,
help="number of times that a task is executed repeatedly"
)
group3.add_argument(
"--retry",
action="store",
type=str,
dest=ConfigConst.retry,
default="",
help="Specify retry command"
)
group3.add_argument(
"--auto_retry",
dest=ConfigConst.auto_retry,
type=int,
default=0,
help="- the count of auto retry"
)
parser.add_argument(
"-di", "--device_info",
dest=ConfigConst.device_info,
action="store",
type=str,
help="- describe device info in json style"
)
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("-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("--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("-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("-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("--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):
para_list_len = len(para_list)
if para_list_len <= 1:
para_list.insert(1, Task.EMPTY_TASK)
elif para_list_len > 1:
item1 = str(para_list[1])
if "-" in item1 and not re.match(r'\d{4}-(?:\d{2}-){5}\d{6}', item1):
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)
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)
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))
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)
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)
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):
test_file = options.testfile.strip()
if test_file and Variables.config.enable_cluster():
from _core.cluster.utils import console_create_task
if console_create_task(test_file):
return
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)
def _process_command_list(self, command, para_list):
if command != ToolCommandType.toolcmd_key_list:
LOG.error("Wrong list command.")
return
if Variables.config.enable_cluster():
self._cluster_list(para_list)
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:
EnvironmentManager().list_devices()
else:
self._list_task_id(para_list[1])
return
EnvironmentManager().list_devices()
@staticmethod
def _cluster_list(para_list):
from _core.cluster.utils import console_list_devices
from _core.cluster.utils import console_list_task
if len(para_list) > 1:
item = para_list[1]
if item == "history":
console_list_task()
elif item == "devices" or item == Task.EMPTY_TASK:
console_list_devices()
else:
console_list_task(task_id=item)
return
console_list_devices()
@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):
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
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
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:
if "#" not in failed:
class_name = "-"
test = "-"
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
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):
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 <module name>;<module name>
run -tf test/resource/<test file name>.txt
run –l <module name> -sn <device serial number>;<device serial number>
run –l <module name> -respath <path of resource>
run –l <module name> -ta size:large
run –l <module name> –ta class:<package>#<class>#<method>
run –l <module name> -ta size:large -pt
run –l <module name> –env <the content string of user_config.xml>
run –l <module name> –e device
run –l <module name> –t ALL
run –l <module name> –td CppTest
run –l <module name> -tcpath resource/testcases
run ssts
run ssts –tc <python script name>;<python script name>
run ssts -sn <device serial number>;<device serial number>
run ssts -respath <path of resource>
... ...
run acts
run acts –tc <python script name>;<python script name>
run acts -sn <device serial number>;<device serial number>
run acts -respath <path of resource>
... ...
run hits
... ...
run --retry
run --retry --session <report folder name>
run --retry --dryrun
"""
LIST_INFORMATION = "list:" + """
This command is used to display device list and task record.\n
usage:
list
list history
list <id>
Introduction:
list: display device list
list history: display history record of a serial of tasks
list <id>: 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
"""