1、修复测试用例时间计算问题 2、C++驱动增加支持豁免 3、修复retry命令的bug

Signed-off-by: deveco_xdevice <liguangjie1@huawei.com>
This commit is contained in:
deveco_xdevice 2023-04-20 18:10:32 +08:00
parent 32f406233b
commit 231d3fe12b
10 changed files with 126 additions and 90 deletions

View File

@ -405,6 +405,8 @@ class OHJSUnitTestDriver(IDriver):
json_config.get_driver(), False)
if testcase_timeout:
self.runner.add_arg("timeout", int(testcase_timeout))
self.runner.compile_mode = get_config_value(
'compile-mode', json_config.get_driver(), False)
def _do_test_run(self, listener):
test_to_run = self._collect_test_to_run()
@ -561,6 +563,7 @@ class OHJSUnitTestRunner:
self.expect_tests_dict = dict()
self.finished_observer = None
self.retry_times = 1
self.compile_mode = ""
def dry_run(self):
parsers = get_plugin(Plugin.PARSER, CommonParserType.oh_jsunit_list)
@ -628,34 +631,40 @@ class OHJSUnitTestRunner:
if self.config.package_name:
# aa test -p ${packageName} -b ${bundleName}-s
# unittest OpenHarmonyTestRunner
command = "aa test -p %s -b %s -s unittest OpenHarmonyTestRunner" \
" %s" % (self.config.package_name,
self.config.bundle_name,
self.get_args_command())
command = "aa test -p {} -b {} -s unittest OpenHarmonyTestRunner" \
" {}".format(self.config.package_name,
self.config.bundle_name,
self.get_args_command())
elif self.config.module_name:
# aa test -m ${moduleName} -b ${bundleName}
# -s unittest OpenHarmonyTestRunner
command = "aa test -m %s -b %s -s unittest OpenHarmonyTestRunner" \
" %s" % (self.config.module_name,
self.config.bundle_name,
self.get_args_command())
command = "aa test -m {} -b {} -s unittest {} {}".format(
self.config.module_name, self.config.bundle_name,
self.get_oh_test_runner_path(), self.get_args_command())
return command
def _get_dry_run_command(self):
command = ""
if self.config.package_name:
command = "aa test -p %s -b %s -s unittest OpenHarmonyTestRunner" \
" %s -s dryRun true" % (self.config.package_name,
self.config.bundle_name,
self.get_args_command())
command = "aa test -p {} -b {} -s unittest OpenHarmonyTestRunner" \
" {} -s dryRun true".format(self.config.package_name,
self.config.bundle_name,
self.get_args_command())
elif self.config.module_name:
command = "aa test -m %s -b %s -s unittest OpenHarmonyTestRunner" \
" %s -s dryRun true" % (self.config.module_name,
self.config.bundle_name,
self.get_args_command())
command = "aa test -m {} -b {} -s unittest {}" \
" {} -s dryRun true".format(self.config.module_name,
self.config.bundle_name,
self.get_oh_test_runner_path(),
self.get_args_command())
return command
def get_oh_test_runner_path(self):
if self.compile_mode == "esmodule":
return "/ets/testrunner/OpenHarmonyTestRunner"
else:
return "OpenHarmonyTestRunner"
@Plugin(type=Plugin.DRIVER, id=DeviceTestType.oh_rust_test)
class OHRustTestDriver(IDriver):

View File

@ -215,7 +215,10 @@ class Device(IDevice):
return False
LOG.debug("Wait device %s to recover" % self.device_sn)
return self.device_state_monitor.wait_for_device_available()
result = self.device_state_monitor.wait_for_device_available()
if result:
self.device_log_collector.restart_catch_device_log()
return result
def get_device_type(self):
self.label = self.model_dict.get("default", None)
@ -770,7 +773,7 @@ class DeviceLogCollector:
# 清空日志
cmd = "hilog -r"
out = self.device.execute_shell_command(cmd)
cmd = "rm -rf /data/log/hilog/*"
cmd = "rm -rf /data/log/hilog/*.gz"
out = self.device.execute_shell_command(cmd)
# 开始日志任务 设置落盘文件个数最大值1000, 单个文件20M链接https://gitee.com/openharmony/hiviewdfx_hilog
cmd = "hilog -w start -l {} -n 1000".format(log_size)

View File

@ -124,6 +124,7 @@ class DeviceLite(IDevice):
self.device_kernel = ""
self.device = None
self.ifconfig = None
self.device_id = None
self.extend_value = {}
self.device_lock = threading.RLock()

View File

@ -189,7 +189,9 @@ class LiteHelper:
while time.time() - start_time < timeout:
if not Scheduler.is_execute:
raise ExecuteTerminate("Execute terminate", error_no="00300")
data = com.readline().decode('gbk', errors='ignore')
if com.in_waiting == 0:
continue
data = com.read(com.in_waiting).decode('gbk', errors='ignore')
data = PATTERN.sub('', data).replace("\r", "")
result = "{}{}".format(result, data)
if receiver and data:

View File

@ -33,6 +33,7 @@ from xdevice import TestDescription
from xdevice import ResultCode
from xdevice import CommonParserType
from xdevice import get_cst_time
from xdevice import get_delta_time_ms
__all__ = ["CppTestParser", "CppTestListParser", "JunitParser", "JSUnitParser",
"OHKernelTestParser", "OHJSUnitTestParser",
@ -83,6 +84,8 @@ class CppTestParser(IParser):
self.product_info = {}
self.is_params = False
self.result_data = ""
self.start_time = get_cst_time()
self.suite_start_time = get_cst_time()
def get_suite_name(self):
return self.suite_name
@ -199,6 +202,7 @@ class CppTestParser(IParser):
test_result = self.state_machine.test(reset=True)
test_result.test_class = test_class
test_result.test_name = test_name
self.start_time = get_cst_time()
for listener in self.get_listeners():
test_result = copy.copy(test_result)
listener.__started__(LifeCycle.TestCase, test_result)
@ -218,7 +222,9 @@ class CppTestParser(IParser):
test_class, test_name, run_time = self.parse_test_description(
message)
test_result = self.state_machine.test()
test_result.run_time = int(run_time)
test_result.run_time = get_delta_time_ms(self.start_time)
if test_result.run_time == 0 or test_result.run_time < run_time:
test_result.run_time = run_time
test_result.code = test_status.value
test_result.current = self.state_machine.running_test_index + 1
if not test_result.is_running():
@ -277,6 +283,7 @@ class CppTestParser(IParser):
test_suite = self.state_machine.suite()
test_suite.suite_name = matcher.group(2)
test_suite.test_num = expected_test_num
self.suite_start_time = get_cst_time()
for listener in self.get_listeners():
suite_report = copy.copy(test_suite)
listener.__started__(LifeCycle.TestSuite, suite_report)
@ -284,8 +291,9 @@ class CppTestParser(IParser):
def handle_suite_ended_tag(self, message):
self.state_machine.running_test_index = 0
suite_result = self.state_machine.suite()
suite_result.run_time = get_delta_time_ms(self.suite_start_time)
matcher = re.match(r'.*\((\d+) ms total\)', message)
if matcher:
if matcher and suite_result.run_time == 0:
suite_result.run_time = int(matcher.group(1))
suite_result.is_completed = True
for listener in self.get_listeners():
@ -672,7 +680,7 @@ class JSUnitParser(IParser):
def parse_test_description(self, message):
pattern = r".*\[(pass|fail|error)\]"
year = time.strftime("%Y")
match_list = ["app Log:", "JSApp:", "JsApp:"]
match_list = ["app Log:", "JSApp:", "JsApp:", "JSAPP:"]
filter_message = ""
for keyword in match_list:
if keyword in message:
@ -1039,6 +1047,7 @@ class OHJSUnitItemConstants(Enum):
NUM_TESTS = "numtests"
STACK = "stack"
SUITE_CONSUMING = "suiteconsuming"
CONSUMING = "consuming"
APP_DIED = "App died"
@ -1052,6 +1061,7 @@ class OHJSUnitTestParser(IParser):
self.current_key = None
self.current_value = None
self.start_time = get_cst_time()
self.suite_start_time = get_cst_time()
self.test_time = 0
self.test_run_finished = False
self.cur_sum = -1
@ -1106,6 +1116,7 @@ class OHJSUnitTestParser(IParser):
self.current_key = None
self.current_value = None
self.state_machine.running_test_index = 0
self.suite_start_time = get_cst_time()
for listener in self.get_listeners():
suite = copy.copy(current_suite)
listener.__started__(LifeCycle.TestSuite, suite)
@ -1114,6 +1125,9 @@ class OHJSUnitTestParser(IParser):
if self.current_key == OHJSUnitItemConstants.SUITE_CONSUMING.value:
self.test_time = int(self.current_value)
self.handle_suite_end()
elif self.current_key == OHJSUnitItemConstants.CONSUMING.value:
self.test_time = int(self.current_value)
self.handle_case_end()
else:
self.submit_current_key_value()
self.parse_key(line, len(OHJSUnitPrefixes.STATUS.value))
@ -1147,7 +1161,6 @@ class OHJSUnitTestParser(IParser):
if self.check_legality(test_info.test_class) and \
self.check_legality(test_info.test_name):
self.report_result(test_info)
self.clear_current_test_info()
def clear_current_test_info(self):
self.state_machine.current_test = None
@ -1165,44 +1178,18 @@ class OHJSUnitTestParser(IParser):
if test_info.code == StatusCodes.FAILURE.value:
self.state_machine.running_test_index += 1
test_info.current = self.state_machine.running_test_index
end_time = get_cst_time()
run_time = (end_time - self.start_time).total_seconds()
test_info.run_time = int(run_time * 1000)
for listener in self.get_listeners():
result = copy.copy(test_info)
result.code = ResultCode.FAILED.value
listener.__ended__(LifeCycle.TestCase, result)
if listener.__class__.__name__ == "ReportListener" \
and self.runner.retry_times > 1:
index = list(listener.tests.keys())[-1]
listener.tests.pop(index)
test_info.is_completed = True
test_info.code = ResultCode.FAILED.value
test_info.run_time = get_delta_time_ms(self.start_time)
elif test_info.code == StatusCodes.ERROR.value:
self.state_machine.running_test_index += 1
test_info.current = self.state_machine.running_test_index
end_time = get_cst_time()
run_time = (end_time - self.start_time).total_seconds()
test_info.run_time = int(run_time * 1000)
for listener in self.get_listeners():
result = copy.copy(test_info)
result.code = ResultCode.FAILED.value
listener.__ended__(LifeCycle.TestCase, result)
if listener.__class__.__name__ == "ReportListener" \
and self.runner.retry_times > 1:
index = list(listener.tests.keys())[-1]
listener.tests.pop(index)
test_info.is_completed = True
test_info.code = ResultCode.FAILED.value
test_info.run_time = get_delta_time_ms(self.start_time)
elif test_info.code == StatusCodes.SUCCESS.value:
self.state_machine.running_test_index += 1
test_info.current = self.state_machine.running_test_index
end_time = get_cst_time()
run_time = (end_time - self.start_time).total_seconds()
test_info.run_time = int(run_time * 1000)
for listener in self.get_listeners():
result = copy.copy(test_info)
result.code = ResultCode.PASSED.value
listener.__ended__(LifeCycle.TestCase, result)
test_info.is_completed = True
test_info.code = ResultCode.PASSED.value
test_info.run_time = get_delta_time_ms(self.start_time)
@classmethod
def output_stack_trace(cls, test_info):
@ -1227,9 +1214,26 @@ class OHJSUnitTestParser(IParser):
LOG.debug(self.result_data)
self.result_data = ""
def handle_case_end(self):
test_info = self.state_machine.test()
if test_info.run_time == 0 or test_info.run_time < self.test_time:
test_info.run_time = self.test_time
for listener in self.get_listeners():
result = copy.copy(test_info)
result.code = test_info.code
listener.__ended__(LifeCycle.TestCase, result)
if listener.__class__.__name__ == "ReportListener" \
and self.runner.retry_times > 1:
index = list(listener.tests.keys())[-1]
listener.tests.pop(index)
test_info.is_completed = True
self.clear_current_test_info()
def handle_suite_end(self):
suite_result = self.state_machine.suite()
suite_result.run_time = self.test_time
suite_result.run_time = get_delta_time_ms(self.suite_start_time)
if suite_result.run_time == 0:
suite_result.run_time = self.test_time
suite_result.is_completed = True
for listener in self.get_listeners():
suite = copy.copy(suite_result)
@ -1264,7 +1268,7 @@ class OHJSUnitTestParser(IParser):
for suite in report_listener.suites.values():
test_des_list = self.runner.expect_tests_dict.get(
suite.suite_name, [])
pos = self.runner.suite_recorder.get(suite.suite_name)[0]
pos = self.runner.suite_recorder.get(suite.suite_name)[0]
if len(test_des_list) == len(report_listener.result[pos][1]):
continue
interval = len(test_des_list) - len(report_listener.result[pos][1])

View File

@ -104,6 +104,7 @@ from _core.utils import modify_props
from _core.utils import get_shell_handler
from _core.utils import get_decode
from _core.utils import get_cst_time
from _core.utils import get_delta_time_ms
from _core.utils import get_device_proc_pid
from _core.utils import start_standing_subprocess
from _core.utils import stop_standing_subprocess
@ -238,6 +239,7 @@ __all__ = [
"get_shell_handler",
"get_decode",
"get_cst_time",
"get_delta_time_ms",
"get_device_proc_pid",
"start_standing_subprocess",
"stop_standing_subprocess",

View File

@ -20,6 +20,7 @@ import os
import time
import datetime
import sys
import tempfile
from abc import abstractmethod
from abc import ABCMeta
@ -354,8 +355,7 @@ class DeviceSelector(Selector):
class Cache:
def __init__(self):
from xdevice import Variables
self.cache_file = os.path.join(Variables.res_dir, "cache.dat")
self.cache_file = os.path.join(tempfile.gettempdir(), "cache.dat")
self.expire_time = 1 # days
def check_cache_if_expire(self):

View File

@ -261,8 +261,8 @@ class SuiteReporter:
case_stacktrace = case_stacktrace.replace(chr(char_index), "")
test_case_attributes = {ReportConstant.name: case_result.test_name,
ReportConstant.status: "",
ReportConstant.time: float(
case_result.run_time) / 1000,
ReportConstant.time: round(float(
case_result.run_time) / 1000, 3),
ReportConstant.class_name:
case_result.test_class,
ReportConstant.result: "",

View File

@ -137,6 +137,37 @@ def junit_para_parse(device, junit_paras, prefix_char="-e"):
return " ".join(ret_str)
def get_include_tests(para_datas, test_types, runner):
case_list = []
if test_types == "class":
case_list = para_datas
else:
for case_file in para_datas:
flags = os.O_RDONLY
modes = stat.S_IWUSR | stat.S_IRUSR
with os.fdopen(os.open(case_file, flags, modes), "r") as file_desc:
case_list.extend(file_desc.read().splitlines())
runner.add_instrumentation_arg("gtest_filter", ":".join(case_list).replace("#", "."))
def get_all_test_include(para_datas, test_types, runner, request):
case_list = []
if test_types == "notClass":
case_list = para_datas
else:
if para_datas:
flags = os.O_RDONLY
modes = stat.S_IWUSR | stat.S_IRUSR
with os.fdopen(os.open(para_datas[0], flags, modes), "r") as file_handler:
json_data = json.load(file_handler)
exclude_list = json_data.get(DeviceTestType.cpp_test, [])
for exclude in exclude_list:
if request.get_module_name() in exclude:
temp = exclude.get(request.get_module_name())
case_list.extend(temp)
runner.add_instrumentation_arg("gtest_filter", "{}{}".format("-", ":".join(case_list)).replace("#", "."))
def gtest_para_parse(gtest_paras, runner, request):
"""To parse the para of gtest
Args:
@ -144,40 +175,18 @@ def gtest_para_parse(gtest_paras, runner, request):
Returns:
the new para using in gtest
"""
ret_str = []
if not isinstance(gtest_paras, dict):
LOG.warning("The para of gtest is not the dict format as required")
return ""
for para in gtest_paras.keys():
if para.strip() == 'test-file-include-filter':
case_list = []
files = gtest_paras.get(para)
for case_file in files:
flags = os.O_RDONLY
modes = stat.S_IWUSR | stat.S_IRUSR
with os.fdopen(os.open(case_file, flags, modes),
"r") as file_desc:
case_list.extend(file_desc.read().splitlines())
runner.add_instrumentation_arg("gtest_filter", ":".join(case_list))
if para.strip() == 'all-test-file-exclude-filter':
json_file_list = gtest_paras.get("all-test-file-exclude-filter")
if json_file_list:
flags = os.O_RDONLY
modes = stat.S_IWUSR | stat.S_IRUSR
with os.fdopen(os.open(json_file_list[0], flags, modes),
"r") as file_handler:
json_data = json.load(file_handler)
exclude_list = json_data.get(DeviceTestType.cpp_test, [])
for exclude in exclude_list:
if request.get_module_name() in exclude:
case_list = exclude.get(request.get_module_name())
runner.add_instrumentation_arg(
"gtest_filter",
"%s%s" % ("-", ":".join(case_list)))
return " ".join(ret_str)
test_types = para.strip()
para_datas = gtest_paras.get(para)
if test_types in ["test-file-include-filter", "class"]:
get_include_tests(para_datas, test_types, runner)
elif test_types in ["all-test-file-exclude-filter", "notClass"]:
get_all_test_include(para_datas, test_types, runner, request)
return ""
def reset_junit_para(junit_para_str, prefix_char="-e", ignore_keys=None):

View File

@ -702,6 +702,12 @@ def get_cst_time():
return datetime.now(tz=cn_tz)
def get_delta_time_ms(start_time):
end_time = get_cst_time()
delta = round(float((end_time - start_time).total_seconds()) * 1000, 3)
return delta
def get_device_proc_pid(device, proc_name, double_check=False):
if not hasattr(device, "execute_shell_command") or \
not hasattr(device, "log") or \