diff --git a/config/framework_config.xml b/config/framework_config.xml
index 4bad38c2c0da378adf6bfcb9c0f4c6a7a04db1de..c76070f858af545734b9cc1f44307d3e84ba10a9 100755
--- a/config/framework_config.xml
+++ b/config/framework_config.xml
@@ -23,6 +23,9 @@
+
@@ -52,6 +55,7 @@
+
diff --git a/src/core/build/build_manager.py b/src/core/build/build_manager.py
index 0f95c6da19ba3ca517ba42a67f408f3b487c1caa..dc0c6b4815135fc98da4a34925a0600e540c8b8a 100755
--- a/src/core/build/build_manager.py
+++ b/src/core/build/build_manager.py
@@ -48,6 +48,10 @@ class BuildManager(object):
gn_file.write(" ]\n")
gn_file.write("}\n")
+ # 根据目标编译测试用例
+ # project_root_path 工程根目录
+ # product_form 产品形态,指令第一步选择的产品
+ # build_target 编译目标
@classmethod
def _compile_test_cases_by_target(cls, project_root_path, product_form,
build_target):
@@ -60,6 +64,19 @@ class BuildManager(object):
build_result = False
return build_result
+ # 根据目标编译acts测试用例
+ # project_root_path 工程根目录
+ # para 指令参数
+ @classmethod
+ def _compile_acts_test_cases(cls, project_root_path, para):
+ if BuildTestcases(project_root_path).build_acts_testcases(para):
+ LOG.info("Acts test case compilation successed.")
+ build_result = True
+ else:
+ LOG.info("Acts test compilation failed, please modify.")
+ build_result = False
+ return build_result
+
@classmethod
def _compile_fuzz_test_case(cls, project_root_path, para):
build_result = BuildTestcases(
@@ -70,19 +87,23 @@ class BuildManager(object):
LOG.info("Test case compilation failed, please modify.")
return build_result
+ # 编译入口
def _compile_testcases(self, project_root_path, para):
+ # 获取所有支持的产品,3.1Release版本为["DAYU","Hi3516DV300","ohos-arm64","ohos-sdk","rk3568"]
all_product_list = scan_support_product()
if para.productform not in all_product_list:
from core.build.build_lite_manager import BuildLiteManager
build_lite_manager = BuildLiteManager(project_root_path)
return build_lite_manager.build_testcases(para)
+ # 如果测试集不为空,build_target为测试集
if para.testsuit != "":
return self._compile_test_cases_by_target(
project_root_path,
para.productform,
para.testsuit)
+ # 如果测试集为空,部件列表为空,模块列表为空,测试类型中含有“ALL”,build_target为"make_test"
if (len(para.partname_list) == 0 and para.testmodule == "" and
"ALL" in para.testtype):
return self._compile_test_cases_by_target(
@@ -90,16 +111,18 @@ class BuildManager(object):
para.productform,
"make_test")
+ # 如果测试集为空,三个条件(部件列表为空,模块列表为空,测试类型中含有“ALL”)不同时成立
target_list = SelectTargets(
project_root_path).filter_build_targets(para)
if len(target_list) == 0:
LOG.warning("No build target found.")
return False
+ # 路径拼接 build_cfg_filepath = OpenHarmony/test/developertest/BUILD.gn
build_cfg_filepath = os.path.join(project_root_path,
- "test",
- "developertest",
- "BUILD.gn")
+ "test",
+ "developertest",
+ "BUILD.gn")
self._make_gn_file(build_cfg_filepath, target_list)
if "fuzztest" in para.testtype:
@@ -155,7 +178,14 @@ class BuildManager(object):
LOG.info("**************************************************")
LOG.info("")
- build_result = self._compile_testcases(project_root_path, param)
+ build_acts_result = True
+ build_result = True
+ if "actstest" in param.testtype:
+ LOG.info("**********************Start build acts testcases****************************")
+ build_acts_result = self._compile_acts_test_cases(project_root_path, param)
+ else:
+ LOG.info("**********************Start build subsystem testcases****************************")
+ build_result = self._compile_testcases(project_root_path, param)
LOG.info("")
LOG.info("**************************************************")
@@ -163,7 +193,7 @@ class BuildManager(object):
LOG.info("**************************************************")
LOG.info("")
- return build_result
+ return build_result and build_acts_result
##############################################################################
diff --git a/src/core/build/build_testcases.py b/src/core/build/build_testcases.py
index 3d07569932c1c85614805a3f9f8db3b951345960..d3e8730d678dd213223e087128b4e2078e841bf0 100755
--- a/src/core/build/build_testcases.py
+++ b/src/core/build/build_testcases.py
@@ -31,6 +31,9 @@ from core.config.config_manager import UserConfigManager
BUILD_FILEPATH = "./build.sh"
BUILD_LITE = "build/lite/build.py"
BUILD_TARGET_PLATFORM = "build_platform=\"%s\""
+BUILD_PRODUCT_NAME = "product_name=%s"
+BUILD_TARGET_SUBSYSTEM = "target_subsystem=%s"
+BUILD_TARGET_SUITE = "suite=%s"
LOG = platform_logger("BuildTestcases")
@@ -40,7 +43,10 @@ LOG = platform_logger("BuildTestcases")
class BuildTestcases(object):
def __init__(self, project_rootpath):
self.project_rootpath = project_rootpath
-
+ self.xts_project_rootpath = os.path.join(sys.source_code_root_path,
+ "test",
+ "xts",
+ "acts")
user_manager = UserConfigManager()
self.is_build_example = user_manager.get_user_config_flag(
"build", "example")
@@ -67,6 +73,8 @@ class BuildTestcases(object):
return ""
testcase_outpath = ""
+
+ # 路径注释 get_build_output_path = OpenHarmony/out/rk3568/build_configs/platforms_info/toolchain_to_variant.json
toolchain_filepath = os.path.join(
get_build_output_path(productform),
"build_configs",
@@ -86,6 +94,18 @@ class BuildTestcases(object):
testcase_outpath = testcase_outpath[pos:len(testcase_outpath)]
return testcase_outpath
+ @classmethod
+ def _delete_acts_testcase_dir(cls, productform):
+ acts_testcase_out_dir = os.path.join(
+ get_build_output_path(productform),
+ "suites",
+ "acts",
+ "testcases")
+ LOG.info("acts_testcase_out_dir=%s" % acts_testcase_out_dir)
+ # 删除~/OpenHarmony/out/rk3568/suites/acts/testcases目录内容
+ if os.path.exists(acts_testcase_out_dir):
+ shutil.rmtree(acts_testcase_out_dir)
+
def _delete_testcase_dir(self, productform):
if is_open_source_product(productform):
package_out_dir = os.path.join(
@@ -101,12 +121,14 @@ class BuildTestcases(object):
"tests")
LOG.info("package_out_dir=%s" % package_out_dir)
+ # 删除~/OpenHarmony/out/rk3568/packages/phone/tests目录内容
if os.path.exists(package_out_dir):
shutil.rmtree(package_out_dir)
phone_out_dir = os.path.join(
self.project_rootpath, "out", "release", "tests")
LOG.info("phone_out_dir=%s" % phone_out_dir)
+ # 删除~/OpenHarmony/out/release/tests目录内容
if os.path.exists(phone_out_dir):
shutil.rmtree(phone_out_dir)
@@ -177,6 +199,32 @@ class BuildTestcases(object):
os.chdir(current_path)
return build_result
+ def _execute_build_acts_command(self, para):
+ build_result = False
+ acts_build_command = []
+ current_path = os.getcwd()
+ # acts_rootpath = ~/OpenHarmony/test/xts/acts
+ os.chdir(self.xts_project_rootpath)
+ acts_build_command.append(BUILD_PRODUCT_NAME % para.productform)
+ acts_build_command.append("system_size=standard")
+ if len(para.subsystem) > 0:
+ acts_build_command.append(BUILD_TARGET_SUBSYSTEM % para.subsystem[0])
+ if para.testsuit != "":
+ acts_build_command.append(BUILD_TARGET_SUITE % para.testsuit)
+ if os.path.exists(BUILD_FILEPATH):
+ build_command = [BUILD_FILEPATH]
+ build_command.extend(acts_build_command)
+ LOG.info("build_acts_command: %s" % str(build_command))
+ if subprocess.call(build_command) == 0:
+ build_result = True
+ else:
+ build_result = False
+ else:
+ LOG.warning("Build Acts Testcase Error: The %s is not exist" % BUILD_FILEPATH)
+
+ os.chdir(current_path)
+ return build_result
+
def build_fuzz_testcases(self, para):
self._delete_testcase_dir(para.productform)
helper_path = os.path.join("..", "libs", "fuzzlib", "fuzzer_helper.py")
@@ -189,6 +237,7 @@ class BuildTestcases(object):
self._merge_testcase_dir(para.productform)
return build_result
+ # 编译测试用例(编译命令拼接)
def build_testcases(self, productform, target):
command = []
if self.is_build_example:
@@ -203,6 +252,12 @@ class BuildTestcases(object):
self._merge_testcase_dir(productform)
return build_result
+ # 编译ACTS测试用例
+ def build_acts_testcases(self, para):
+ self._delete_acts_testcase_dir(para.productform)
+ build_result = self._execute_build_acts_command(para)
+ return build_result
+
def build_gn_file(self, productform):
command = []
if self.is_build_example:
diff --git a/src/core/build/select_targets.py b/src/core/build/select_targets.py
index 912a6d942592669afeac12d70effceb40813f339..ce6c88cf8c3d4c6fe19243c490230374d30c1771 100755
--- a/src/core/build/select_targets.py
+++ b/src/core/build/select_targets.py
@@ -48,7 +48,7 @@ class SelectTargets(object):
def _get_part_path_data(cls, productform):
part_path_dic = {}
parser = ParsePartsConfig(productform)
-
+ # 获取infos_for_testfwk.json配置文件中“phone”节点下“part_infos”节点数据
part_infos = parser.get_part_infos()
if part_infos is None:
LOG.error("part_infos is None.")
@@ -63,13 +63,14 @@ class SelectTargets(object):
build_out_dir = part_info.get("build_out_dir")
part_path_list = []
+ # default_part_path:~/OpenHarmony/out/rk3568/module_list_files/部件名(以rk3568举例)
default_part_path = os.path.join(
get_build_output_path(productform),
"module_list_files",
origin_part_name)
if os.path.exists(default_part_path):
part_path_list.append(default_part_path)
-
+ # 如果build_out_dir不是当前目录,将新目录加到part_path_list中
if build_out_dir != ".":
product_part_path = os.path.join(
get_build_output_path(productform),
@@ -84,12 +85,18 @@ class SelectTargets(object):
def _get_target_list_from_path(self, typelist, check_path):
target_list = []
if os.path.exists(check_path):
+ # 获取部件编译输出目录(~/OpenHarmony/out/rk3568/module_list_files/部件名1)中.mlf文件列表
mlf_file_list = get_file_list_by_postfix(
check_path, ".mlf")
+ # 遍历mlf_file_list中所有目录下面mlf文件中的label列表
for filepath in mlf_file_list:
+ # 获取mlf文件中的JSON数据信息列表
mlf_info_list = self._get_mlf_data_from_file(filepath)
for data in mlf_info_list:
+ # 举例:"test_type": "moduletest"
test_type = data.get("test_type")
+ # 举例:"label": "//base/accessibility/services/test:aams_accessibility_keyevent_filter_test
+ # (//build/toolchain/ohos:ohos_clang_arm)"
target_path = data.get("label")
if "ALL" in typelist:
target_list.append(target_path)
@@ -100,6 +107,8 @@ class SelectTargets(object):
def _get_target_list_by_type(self, productform, typelist):
target_list = []
+ # 获取所有部件编译输出信息列表:[{“部件名1”:[~/OpenHarmony/out/rk3568/module_list_files/部件名1]}]
+ # 或者{“部件名1”:[~/OpenHarmony/out/rk3568/module_list_files/部件名1,~/OpenHarmony/out/rk3568/编译目录build_out_dir/module_list_files/部件名1]}
part_path_dic = self._get_part_path_data(productform)
for item in part_path_dic:
part_path_list = part_path_dic.get(item)
@@ -147,16 +156,19 @@ class SelectTargets(object):
LOG.warning(
"The part cannot be empty When the module is not empty.")
return []
-
+ # productform不为空,typelist(test type[UT,MST,ST,PERF,ALL])不为空
+ # partlist和testmodule为空,通过testtype获取部件列表
if len(partlist) == 0 and testmodule == "":
target_list = self._get_target_list_by_type(productform, typelist)
return target_list
-
+ # productform不为空,typelist(test type[UT,MST,ST,PERF,ALL])不为空
+ # partlist不为空,testmodule为空,通过testtype、partlist一起获取部件列表
if len(partlist) != 0 and testmodule == "":
target_list = self._get_target_list_by_part(productform, typelist,
partlist)
return target_list
-
+ # productform不为空,typelist(test type[UT,MST,ST,PERF,ALL])不为空
+ # partlist不为空,testmodule不为空,通过testtype、partlist、testmodule一起获取部件列表
if len(partlist) != 0 and testmodule != "":
target_list = self._get_target_list_by_module(productform,
typelist,
@@ -165,6 +177,11 @@ class SelectTargets(object):
return target_list
+ # 通过infos_for_testfwk.json文件获取所有子部件信息编译目录信息:
+ # [{“部件名1”:[~/OpenHarmony/out/rk3568/module_list_files/部件名1]}]
+ # 然后遍历这些目录中的mlf文件,获取其中定义的label,返回label集合
+ # 遍历时通过testmodule控制遍历的部件指定模块目录,如果不定义,则遍历子部件下面所有模块目录
+ # 遍历时通过partlist控制遍历指定部件目录,如果不定义,则遍历infos_for_testfwk.json文件中定义的所有子部件目录
def filter_build_targets(self, para):
productform = para.productform
typelist = para.testtype
diff --git a/src/core/command/console.py b/src/core/command/console.py
index a8b38225b68b649bed148d14b360e8c1eca836a1..87c3e9ef2028b815cfd5797d1f5d64d21b4b00f7 100755
--- a/src/core/command/console.py
+++ b/src/core/command/console.py
@@ -85,6 +85,7 @@ class Console(object):
else:
self.command_parser(" ".join(args[1:]))
+ # 命令执行总入口
def _console(self):
if platform.system() != 'Windows':
signal.signal(signal.SIGTSTP, self.handler_ctrl_z) # ctrl+x linux
@@ -92,9 +93,11 @@ class Console(object):
while True:
try:
+ # 获取用户命令输入
usr_input = input(">>> ")
if usr_input == "":
continue
+ # 用户输入命令解析
self.command_parser(usr_input)
except SystemExit:
LOG.info("Program exit normally!")
@@ -102,6 +105,7 @@ class Console(object):
except (IOError, EOFError, KeyboardInterrupt) as error:
LOG.exception("Input Error: %s" % error)
+ # 参数解析方法
@classmethod
def argument_parser(cls, para_list):
"""
@@ -113,6 +117,8 @@ class Console(object):
parser = None
try:
+ # argparse是一个Python模块:命令行选项、参数和子命令解析器
+ # 使用argparse的第一步:创建一个ArgumentParser对象,ArgumentParser对象包含将命令行解析成Python数据类型所需的全部信息
parser = argparse.ArgumentParser(description="Specify test para.")
parser.add_argument("action", type=str.lower,
help="Specify action")
@@ -208,6 +214,7 @@ class Console(object):
default="",
help="Specify fuzzer name"
)
+ # 解析部分命令行参数,会返回一个由两个条目构成的元组,其中包含带成员的命名空间(options)和剩余参数字符串的列表(unparsed)
(options, unparsed) = parser.parse_known_args(para_list)
# Set default value
@@ -228,12 +235,14 @@ class Console(object):
def command_parser(self, args):
try:
+ # 将用户输入的指令按空格拆分成字符串数组
para_list = args.split()
options, _, valid_param = self.argument_parser(para_list)
if options is None or not valid_param:
LOG.warning("options is None.")
return
+ # 根据命令行的命令选择不同的方法执行
command = options.action
if command == "":
LOG.warning("action is empty.")
@@ -288,6 +297,7 @@ class Console(object):
LOG.error("Wrong gen command.")
return
+ # run命令执行入口
@classmethod
def _process_command_run(cls, command, options):
if command == ToolCommandType.TOOLCMD_KEY_RUN:
@@ -337,9 +347,6 @@ class Console(object):
if is_build_version:
build_result = build_manager.build_version(project_root_path,
product_form)
- else:
- build_result = build_manager.build_gn_file(project_root_path,
- product_form)
return build_result
diff --git a/src/core/command/display.py b/src/core/command/display.py
index 1a69bbf430f15f90859de30b43000ad235a6ccba..e867c0afe1550c31414b2cffdd05db51bb71cb51 100755
--- a/src/core/command/display.py
+++ b/src/core/command/display.py
@@ -16,6 +16,10 @@
# limitations under the License.
#
+# 执行如下命令 获取到的信息
+# show subsystemlist 通过show subsystemlist得到子系统名称列表
+# show partlist 通过show partlist得到对应子系统下的部件名
+
import sys
import os
@@ -28,12 +32,35 @@ from core.config.config_manager import UserConfigManager
from core.config.config_manager import FrameworkConfigManager
from core.config.parse_parts_config import ParsePartsConfig
+# 支持的设备名称
+# 1. ohos-sdk
+# 2. rk3568
+# 3. Hi3516DV300
+# 4. DAYU
+# 5. ohos-arm64
+# 6. ipcamera_hispark_aries
+# 7. ipcamera_hispark_taurus
+# 8. wifiiot_hispark_pegasus
CMD_KEY_PRODUCTLIST = "productlist"
+
+# 测试用例类型
+# 1. UT
+# 2. MST
+# 3. ST
+# 4. PERF
+# 5. SEC
+# 6. FUZZ
+# 7. RELI
+# 8. DST
+# 9. BENCHMARK
+# 10. ALL
CMD_KEY_TYPELIST = "typelist"
+
+# 子系统名称列表
CMD_KEY_SUBSYSTEMLIST = "subsystemlist"
-CMD_KEY_PARTLIST = "partlist"
-CMD_KEY_MODULELIST = "modulelist"
+# 子系统下的部件名
+CMD_KEY_PARTLIST = "partlist"
TOOL_VERSION_INFO = """Welcome to DeveloperTest V1.0.0.
"""
@@ -58,8 +85,6 @@ SUPPORT_COMMAND_SHOW = """use show [follow command] for more information:
"subsystemlist" + """
""" + \
"partlist" + """
- """ + \
- "modulelist" + """
"""
RUNCASES_INFOMATION = """run:
@@ -71,7 +96,6 @@ usage: run [-p PRODUCTFORM]
[-t [TESTTYPE [TESTTYPE ...]]]
[-ss [SUBSYSTEM [SUBSYSTEM ...]]]
[-tp [TESTPART [TESTPART ...]]]
- [-tm TESTMODULE]
[-ts TESTSUIT]
[-tc TESTCASE]
[-tl TESTLEVEL]
@@ -85,8 +109,6 @@ optional arguments:
Specify test subsystem
-tp [TESTPART [TESTPART ...]], --testpart [TESTPART [TESTPART ...]]
Specify test testpart
- -tm TESTMODULE, --testmodule TESTMODULE
- Specified test module
-ts TESTSUIT, --testsuit TESTSUIT
Specify test suit
-tc TESTCASE, --testcase TESTCASE
@@ -157,12 +179,20 @@ def select_user_input(data_list):
sys.exit(0)
return select_item_value, select_item_index
-
+# 选择productform
def select_productform():
select_value = "phone"
+
+ # scan_support_product() = [DAYU,Hi3516,ohos_arm64,ohos_sdk,rk3568]
scan_product_list = scan_support_product()
+
+ # 从framework_config.xml里取productform节点的value:ipcamera_hispark_aries、ipcamera_hispark_taurus、wifiiot_hispark_pegasus
config_product_list = \
FrameworkConfigManager().get_framework_config("productform")
+
+ # productform_list = [DAYU,Hi3516,ohos_arm64,ohos_sdk,rk3568,
+ # ipcamera_hispark_aries、ipcamera_hispark_taurus、wifiiot_hispark_pegasus]
+
productform_list = scan_product_list + config_product_list
if len(productform_list) != 0:
print("Please select the current tested product form:")
@@ -217,61 +247,6 @@ def display_show_info(para_list, productform):
#############################################################################
#############################################################################
-def get_module_list_from_output_dir(product_form):
- module_path_list = []
- all_product_list = scan_support_product()
- if product_form in all_product_list:
- module_list_file_path = os.path.join(
- get_build_output_path(product_form),
- "module_list_files")
- else:
- module_list_file_path = os.path.join(
- get_build_output_path(product_form),
- "test_info",
- "module_list_files")
- print(module_list_file_path)
- if os.path.exists(module_list_file_path):
- file_list = get_file_list_by_postfix(module_list_file_path, ".mlf")
- for file in file_list:
- module_path = \
- file[len(module_list_file_path) + 1: file.rfind(os.sep)]
- if module_path != "" and module_path not in module_path_list:
- module_path_list.append(module_path)
- else:
- print("%s does not exist." % module_list_file_path)
- module_path_list.sort()
- return module_path_list
-
-
-def get_module_list_from_case_dir(test_case_dir):
- file_list = []
- test_case_tests_path = test_case_dir
- if not os.path.exists(test_case_tests_path):
- return file_list
-
- for test_type in os.listdir(test_case_tests_path):
- file_path = os.path.join(test_case_tests_path, test_type)
- for dirs in os.walk(file_path):
- files = get_file_list(find_path=dirs[0])
- for file_name in files:
- if "" != file_name and -1 == file_name.find(__file__):
- file_name = os.path.join(dirs[0], file_name)
- if os.path.isfile(file_name):
- file_name = file_name[len(file_path) + 1: \
- file_name.rfind(os.sep)]
- file_list.append(file_name)
- return file_list
-
-
-def get_module_list(product_form):
- module_path_list = []
- testcase_dir = UserConfigManager().get_test_cases_dir()
- if testcase_dir == "":
- module_path_list = get_module_list_from_output_dir(product_form)
- else:
- module_path_list = get_module_list_from_case_dir(testcase_dir)
- return module_path_list
-
#############################################################################
#############################################################################
@@ -300,7 +275,7 @@ def show_testtype_list():
else:
print("No category specified.")
-
+# 从OpenHarmony/out/rk3568/build_configs/infos_for_testfwk.json里的subsystem_infos中subsystem_infos下获取subsystemlist
def show_subsystem_list(product_form):
print("List of currently supported subsystem names:")
parser = ParsePartsConfig(product_form)
@@ -312,7 +287,7 @@ def show_subsystem_list(product_form):
for index, element in enumerate(subsystem_name_list):
print(" %d. %s" % (index + 1, element))
-
+# 从OpenHarmony/out/rk3568/build_configs/infos_for_testfwk.json里的subsystem_infos中subsystem_infos下获取partlist
def show_partname_list(product_form):
print("List of currently supported part names:")
parser = ParsePartsConfig(product_form)
@@ -329,35 +304,6 @@ def show_partname_list(product_form):
for index, element in enumerate(part_name_list):
print(" %d. %s" % (index + 1, element))
-
-def show_module_list(product_form):
- print("List of currently supported module names:")
- subsystem_name_list = []
- subsystem_module_list = get_module_list(product_form)
-
- for item in subsystem_module_list:
- if item != "":
- subsystem_name = item.split(os.sep)[0]
- if subsystem_name not in subsystem_name_list:
- subsystem_name_list.append(subsystem_name)
-
- for subsystem_name in subsystem_name_list:
- print("%s:" % subsystem_name)
- index = 0
- module_value_list = []
- for item in subsystem_module_list:
- find_key = subsystem_name + os.sep
- pos_subsystem = item.find(find_key)
- if pos_subsystem >= 0:
- subsystem_module_dir = \
- item[pos_subsystem + len(find_key):len(item)]
- module_value = subsystem_module_dir.split(os.sep)[0]
- if module_value not in module_value_list:
- module_value_list.append(module_value)
- index += 1
- print(" %d. %s" % (index, module_value))
-
-
def display_help_command_info(command):
if command == ToolCommandType.TOOLCMD_KEY_SHOW:
print(SUPPORT_COMMAND_SHOW)
@@ -380,8 +326,6 @@ def display_show_command_info(command, product_form="phone"):
show_subsystem_list(product_form)
elif command == CMD_KEY_PARTLIST:
show_partname_list(product_form)
- elif command == CMD_KEY_MODULELIST:
- show_module_list(product_form)
else:
print("This command is not support.")
diff --git a/src/core/command/run.py b/src/core/command/run.py
index d89d6577e882c39367246e97ec0e78bd5f4ee0b4..f662c012f3ed67a8a6de0cc5a249b443beeb671b 100755
--- a/src/core/command/run.py
+++ b/src/core/command/run.py
@@ -41,17 +41,20 @@ LOG = platform_logger("Run")
class Run(object):
def process_command_run(self, command, options):
para = Parameter()
+ # 过滤options中的test type参数,确保都是合法的,最终的数据结构为:[{unittest:300,moduletest:300}]
test_type_list = para.get_testtype_list(options.testtype)
if len(test_type_list) == 0:
LOG.error("The testtype parameter is incorrect.")
return
options.testtype = test_type_list
-
+ # 初始化ParsePartsConfig,根据productform获取对应的所有子系统名称列表、子系统下的部件名列表
parser = ParsePartsConfig(options.productform)
+ # 获取部件名列表
partname_list = parser.get_part_list(
options.subsystem,
options.testpart)
options.partname_list = partname_list
+ # 获取编译结果输出目录
options.coverage_outpath = self.get_coverage_outpath(options)
LOG.info("")
@@ -68,21 +71,20 @@ class Run(object):
LOG.info("partname_list = %s" % str(options.partname_list))
LOG.info("------------------------------------")
LOG.info("")
-
+ # options参数校验
if not para.check_run_parameter(options):
LOG.error("Input parameter is incorrect.")
return
-
+ # 编译测试用例
if not self._build_test_cases(options):
LOG.error("Build test cases failed.")
return
- test_case_path = self.get_tests_out_path(options.productform)
- if not os.path.exists(test_case_path):
- LOG.error("%s is not exist." % test_case_path)
- return
+ if "actstest" in options.testtype:
+ test_dict = self.get_acts_test_dict(options)
+ else:
+ test_dict = self.get_test_dict(options)
- test_dict = TestCaseManager().get_test_files(test_case_path, options)
if not self._check_test_dictionary(test_dict):
LOG.error("The test file list is empty.")
return
@@ -170,13 +172,14 @@ class Run(object):
if options.coverage:
LOG.info("Coverage testing, no need to compile testcases")
return True
-
+ # 从user_config.xml文件获取的配置,判断是否编译测试用例
is_build_testcase = UserConfigManager().get_user_config_flag(
"build", "testcase")
project_root_path = sys.source_code_root_path
if is_build_testcase and project_root_path != "":
from core.build.build_manager import BuildManager
build_manager = BuildManager()
+ # 实际编译调用逻辑
return build_manager.build_testcases(project_root_path, options)
else:
return True
@@ -216,6 +219,16 @@ class Run(object):
LOG.info("testcase_path=%s" % testcase_path)
return testcase_path
+ @classmethod
+ def get_acts_tests_out_path(cls, product_form):
+ acts_testcase_path = os.path.abspath(os.path.join(
+ get_build_output_path(product_form),
+ "suites",
+ "acts",
+ "testcases"))
+ LOG.info("acts_testcase_path=%s" % acts_testcase_path)
+ return acts_testcase_path
+
@classmethod
def get_coverage_outpath(cls, options):
coverage_out_path = ""
@@ -228,4 +241,18 @@ class Run(object):
LOG.error("Coverage test: coverage_outpath is empty.")
return coverage_out_path
+ def get_acts_test_dict(self, options):
+ # 获取测试用例编译结果路径
+ acts_test_case_path = self.get_acts_tests_out_path(options.productform)
+ acts_test_dict = TestCaseManager().get_acts_test_files(acts_test_case_path, options)
+ return acts_test_dict
+ def get_test_dict(self, options):
+ # 获取测试用例编译结果路径
+ test_case_path = self.get_tests_out_path(options.productform)
+ if not os.path.exists(test_case_path):
+ LOG.error("%s is not exist." % test_case_path)
+ return
+
+ test_dict = TestCaseManager().get_test_files(test_case_path, options)
+ return test_dict
diff --git a/src/core/common.py b/src/core/common.py
index d4ace1e53c152c8f221ce618f5896171dcd80473..52523658a4683a5edfb68fd567a600b0ad3781f1 100755
--- a/src/core/common.py
+++ b/src/core/common.py
@@ -48,6 +48,7 @@ def get_source_code_root_path(path):
def is_open_source_product(product_name):
open_source_products = ["Hi3516DV300"]
+ return True
if product_name in open_source_products:
return True
return False
diff --git a/src/core/config/config_manager.py b/src/core/config/config_manager.py
index 3b463f63ae52793e96ea81cfcf619f5715ca9f77..748ad61632b04c0b5643757c0b623b37c517aff8 100755
--- a/src/core/config/config_manager.py
+++ b/src/core/config/config_manager.py
@@ -24,24 +24,38 @@ from xdevice import platform_logger
from core.constants import ConfigFileConst
LOG = platform_logger("config_manager")
-CONFIG_PATH = os.path.join(sys.framework_res_dir, "config")
+# 变量注释 framework_res_dir = OpenHarmony/test/developertest
+# 变量注释 CONFIG_PATH = OpenHarmony/test/developertest/config
+CONFIG_PATH = os.path.join(sys.framework_res_dir, "config")
+# framework_config.xml
class FrameworkConfigManager(object):
def __init__(self, filepath=""):
if filepath == "":
+
+ # 变量注释 filepath = OpenHarmony/test/developertest/config/framework_config.xml
self.filepath = os.path.abspath(os.path.join(
CONFIG_PATH, ConfigFileConst.FRAMECONFIG_FILEPATH))
else:
self.filepath = filepath
+ # 获取framework_config.xml中所有name的value,返回列表
def get_framework_config(self, target_name):
data_list = []
try:
if os.path.exists(self.filepath):
+
+ # 读取xml文件
tree = ET.parse(self.filepath)
+
+ # 获取根节点
root = tree.getroot()
+
+ # 获取节点的名字
node = root.find(target_name)
+
+ # 遍历 name 节点 获取value 添加到data_list中
for sub in node:
value = sub.attrib.get("name")
if value and value != "":
@@ -50,6 +64,7 @@ class FrameworkConfigManager(object):
LOG.error(("Parse %s fail!" % self.filepath) + xml_exception.args)
return data_list
+ # 获取framework_config.xml中test_category标签里name、desc、timeout的value,返回字典
def get_test_category_info(self, target_name="test_category"):
test_type_timeout_dic = {}
try:
@@ -69,13 +84,17 @@ class FrameworkConfigManager(object):
LOG.error(("Parse %s fail!" % self.filepath) + xml_exception.args)
return test_type_timeout_dic
+ # 获取framework_config.xml中all_category标签里name的value,返回列表 如:unittest、moduletest、systemtest、performance
def get_all_category_info(self, target_name="all_category"):
return self.get_framework_config(target_name)
+# filter_config.xml
class FilterConfigManager(object):
def __init__(self, filepath=""):
if filepath == "":
+
+ # 变量注释 filepath = OpenHarmony/test/developertest/config/filter_config.xml
self.filepath = os.path.abspath(
os.path.join(CONFIG_PATH,
ConfigFileConst.FILTERCONFIG_FILEPATH))
@@ -106,7 +125,7 @@ class FilterConfigManager(object):
def get_filter_config_path(self):
return self.filepath
-
+# 这里的filepath不存在
class ResourceConfigManager(object):
def __init__(self, filepath=""):
if filepath == "":
@@ -142,6 +161,8 @@ class ResourceConfigManager(object):
class UserConfigManager(object):
def __init__(self, config_file=""):
if config_file == "":
+
+ # 变量注释 filepath = OpenHarmony/test/developertest/config/user_config.xml
self.filepath = os.path.abspath(os.path.join(
CONFIG_PATH, ConfigFileConst.USERCONFIG_FILEPATH))
else:
@@ -261,6 +282,8 @@ class UserConfigManager(object):
class BuildConfigManager(object):
def __init__(self, filepath=""):
if filepath == "":
+
+ # 变量注释 filepath = OpenHarmony/test/developertest/config/build_config.xml
self.filepath = os.path.abspath(os.path.join(
CONFIG_PATH, ConfigFileConst.BUILDCONFIG_FILEPATH))
else:
@@ -287,6 +310,8 @@ class BuildConfigManager(object):
class FuzzerConfigManager(object):
def __init__(self, config_path=""):
if config_path == "":
+
+ # 变量注释 filepath = OpenHarmony/test/developertest/config/fuzz_config.xml
self.filepath = self.filepath = os.path.abspath(os.path.join(
CONFIG_PATH, ConfigFileConst.FUZZCONFIG_FILEPATH))
else:
diff --git a/src/core/config/parse_parts_config.py b/src/core/config/parse_parts_config.py
index 3e51417d40a1786073203d8f0d6d31845ff044ae..5a271b7059f7b9ae311d77548caaa12cbfa8c36a 100755
--- a/src/core/config/parse_parts_config.py
+++ b/src/core/config/parse_parts_config.py
@@ -32,10 +32,13 @@ class ParsePartsConfig(object):
self.productform = productform
self.subsystem_infos, self.part_infos = self.get_infos_data()
+ # 获取配置文件地址:~/OpenHarmony/out/rk3568/build_configs/infos_for_testfwk.json(以rk3568举例)
def get_config_file_path(self):
manager = UserConfigManager()
+ # 获取user_config.xml文件中的配置的(编译好的测试用例地址)
testcase_dir = manager.get_test_cases_dir()
+ # 如果没有在developtertest/config/user_config里配置test_cases路径,就到OpenHarmony/out/rk3568/build_configs/infos_for_testfwk.json里查找
if testcase_dir == "":
if sys.source_code_root_path != "":
config_filepath = os.path.join(
@@ -44,6 +47,8 @@ class ParsePartsConfig(object):
"infos_for_testfwk.json")
else:
config_filepath = ""
+
+ # 如果在developtertest/config/user_config里配置了test_cases路径,就在这个路径下的infos_for_testfwk.json里查找
else:
config_filepath = os.path.join(
testcase_dir,
@@ -52,6 +57,8 @@ class ParsePartsConfig(object):
def get_infos_data(self):
config_filepath = self.get_config_file_path()
+
+ # 检验给出的路径是否真地存在
if not os.path.exists(config_filepath):
print("Error: %s is not exist." % config_filepath)
return None, None
@@ -68,11 +75,13 @@ class ParsePartsConfig(object):
product_data_dic = data_dic.get("phone", None)
else:
product_data_dic = data_dic.get(self.productform, None)
+ # product_data_dic:infos_for_testfwk.json配置文件中“phone”节点数据
if product_data_dic is None:
print("Error: product_data_dic is None.")
return None, None
-
+ # subsystem_infos(系统中定义的子系统列表):infos_for_testfwk.json配置文件中“phone”节点下“subsystem_infos”节点数据
subsystem_infos = product_data_dic.get("subsystem_infos", None)
+ # subsystem_infos(系统中定义的部件信息列表):infos_for_testfwk.json配置文件中“phone”节点下“part_infos”节点数据
part_infos = product_data_dic.get("part_infos", None)
return subsystem_infos, part_infos
@@ -89,14 +98,17 @@ class ParsePartsConfig(object):
subsystem_name_list.append(item)
return subsystem_name_list
+ # 获取部件列表
def get_part_list(self, subsystemlist, partlist):
+ # 如果options参数中的partlist不为空,直接返回partlist
if len(partlist) != 0:
return partlist
-
+ # 如果infos_for_testfwk.json配置文件的subsystem_infos为None,返回options参数中的subsystemlist
if self.subsystem_infos is None:
return subsystemlist
part_name_list = []
+ # 遍历options参数中的子系统列表,并且将infos_for_testfwk.json配置文件的subsystem_infos中的对应子系统的部件列表加入到part_name_list中
if len(subsystemlist) != 0:
for item in subsystemlist:
parts = self.subsystem_infos.get(item, [])
diff --git a/src/core/driver/drivers.py b/src/core/driver/drivers.py
index 93177842d572181b58d13e7f72bc5172b6cabdd1..791b97f826813777224a788493263110e38f20a6 100755
--- a/src/core/driver/drivers.py
+++ b/src/core/driver/drivers.py
@@ -25,6 +25,7 @@ import platform
import zipfile
import stat
from dataclasses import dataclass
+from json import JSONDecodeError
from xdevice import DeviceTestType
from xdevice import DeviceLabelType
@@ -658,11 +659,18 @@ class JSUnitTestDriver(IDriver):
def _run_jsunit(self, suite_file, device_log_file):
filename = os.path.basename(suite_file)
+ _, suffix_name = os.path.splitext(filename)
resource_manager = ResourceManager()
- resource_data_dic, resource_dir = \
- resource_manager.get_resource_data_dic(suite_file)
- timeout = ResourceManager.get_nodeattrib_data(resource_data_dic)
+ resource_data_dic, resource_dir = resource_manager.get_resource_data_dic(suite_file)
+ if suffix_name == ".hap":
+ json_file_path = suite_file.replace(".hap", ".json")
+ if os.path.exists(json_file_path):
+ timeout = self._get_json_shell_timeout(json_file_path)
+ else:
+ timeout = ResourceManager.get_nodeattrib_data(resource_data_dic)
+ else:
+ timeout = ResourceManager.get_nodeattrib_data(resource_data_dic)
resource_manager.process_preparer_data(resource_data_dic, resource_dir,
self.config.device)
@@ -800,6 +808,23 @@ class JSUnitTestDriver(IDriver):
_sleep_according_to_result(return_message)
return return_message
+ @classmethod
+ def _get_json_shell_timeout(cls, json_filepath):
+ test_timeout = 300
+ try:
+ with open(json_filepath, 'r') as json_file:
+ data_dic = json.load(json_file)
+ if not data_dic:
+ return test_timeout
+ else:
+ if "driver" in data_dic.keys():
+ driver_dict = data_dic.get("driver")
+ if driver_dict and "test-timeout" in driver_dict.keys():
+ test_timeout = int(driver_dict["shell-timeout"]) / 1000
+ return test_timeout
+ except JSONDecodeError:
+ return test_timeout
+
@staticmethod
def _get_package_and_ability_name(hap_filepath):
package_name = ""
diff --git a/src/core/testcase/testcase_manager.py b/src/core/testcase/testcase_manager.py
index d0ac52af924604fa789f25c1dff2895ea3282e7c..9e6406dfaeeaaa206e76066db962d58072dffa31 100755
--- a/src/core/testcase/testcase_manager.py
+++ b/src/core/testcase/testcase_manager.py
@@ -18,6 +18,12 @@
import os
import copy
+import json
+import sys
+from json import JSONDecodeError
+from core.utils import get_build_output_path
+from core.common import is_open_source_product
+
from core.utils import get_file_list_by_postfix
from core.config.config_manager import FilterConfigManager
from xdevice import platform_logger
@@ -79,22 +85,25 @@ class TestCaseManager(object):
"subsystem_name", options.productform)
filter_list_test_file = FilterConfigManager().get_filtering_list(
"testfile_name", options.productform)
-
+ # 遍历测试用例输出目录下面的所有文件夹,每个文件夹对应一个子系统
for part_name in os.listdir(test_case_out_path):
part_case_dir = os.path.join(test_case_out_path, part_name)
if not os.path.isdir(part_case_dir):
continue
-
+ # 如果子系统在fiter_config.xml配置文件的下面配置过,则过滤
if part_name in filter_part_list:
continue
+ # 获取子系统目录下面的所有文件路径列表
suite_file_list = get_file_list_by_postfix(part_case_dir)
for suite_file in suite_file_list:
+ # 如果文件在resource目录下面,需要过滤
if -1 != suite_file.replace(test_case_out_path, "").find(
os.sep + "resource" + os.sep):
continue
file_name = os.path.basename(suite_file)
+ # 如果文件在fiter_config.xml配置文件的下面配置过,则过滤
if file_name in filter_list_test_file:
continue
@@ -122,6 +131,27 @@ class TestCaseManager(object):
return suite_file_dictionary
+ def get_acts_test_files(self, acts_test_case_path, options):
+ LOG.info("acts test case path: " + acts_test_case_path)
+ acts_suit_file_dic = copy.deepcopy(TESTFILE_TYPE_DATA_DIC)
+ if os.path.exists(acts_test_case_path):
+ # 获取acts测试用例输出目录下面的所有文件路径列表
+ acts_suite_file_list = get_file_list_by_postfix(acts_test_case_path)
+ for acts_suite_file in acts_suite_file_list:
+ file_name = os.path.basename(acts_suite_file)
+ prefix_name, suffix_name = os.path.splitext(file_name)
+ if suffix_name != ".hap":
+ continue
+ # 如果acts测试指定了-ts,只有完全匹配的HAP包才会加入最终执行的队列
+ if options.testsuit != "" and options.testsuit != prefix_name:
+ continue
+ if not self.check_hap_test_file(acts_suite_file):
+ continue
+ acts_suit_file_dic["JST"].append(acts_suite_file)
+ else:
+ LOG.error("acts %s is not exist." % acts_test_case_path)
+ return acts_suit_file_dic
+
@classmethod
def get_valid_suite_file(cls, test_case_out_path, suite_file, options):
partlist = options.partname_list
@@ -166,3 +196,28 @@ class TestCaseManager(object):
if filename.startswith("test_"):
return True
return False
+
+ @classmethod
+ def check_hap_test_file(cls, hap_file_path):
+ try:
+ if hap_file_path.endswith(".hap"):
+ json_file_path = hap_file_path.replace(".hap", ".json")
+ if os.path.exists(json_file_path):
+ with open(json_file_path, 'r') as json_file:
+ data_dic = json.load(json_file)
+ if not data_dic:
+ return False
+ else:
+ if "kits" in data_dic.keys():
+ kits_list = data_dic.get("kits")
+ if len(kits_list) > 0:
+ kits_dict = kits_list[0]
+ if "test-file-name" in kits_dict.keys():
+ return True
+ else:
+ return False
+ else:
+ return False
+ return False
+ except JSONDecodeError:
+ return False
diff --git a/src/core/utils.py b/src/core/utils.py
index fc0a58974ee962884e90903d848494a39edd44bc..21ad7d2d16cce07ebfc24ab340ec429fb891ddba 100755
--- a/src/core/utils.py
+++ b/src/core/utils.py
@@ -49,7 +49,7 @@ def get_file_list(find_path, postfix=""):
file_list.append(file_name)
return file_list
-
+# 获取目录下每一个文件,并放到一个列表里
def get_file_list_by_postfix(path, postfix=""):
file_list = []
for dirs in os.walk(path):
@@ -96,11 +96,13 @@ def get_build_output_path(product_form):
build_output_path = os.path.join(sys.source_code_root_path,
"out",
build_output_name)
+ # 返回编译结果输出目录:~/OpenHarmony/out/rk3568(以rk3568举例)
return build_output_path
def scan_support_product():
# scan standard and large system info
+ # product_form_dir = OpenHarmony/productdefine/common/products/
product_form_dir = os.path.join(sys.source_code_root_path,
"productdefine",
"common",
diff --git a/src/main/_init_global_config.py b/src/main/_init_global_config.py
index f01dcedf990702fef6c1dd6fb8d3dece5797612a..865870ba39dcbf6cd9d183ddb52adf302c098680 100755
--- a/src/main/_init_global_config.py
+++ b/src/main/_init_global_config.py
@@ -22,12 +22,20 @@ def _init_global_config():
import os
# insert src path for loading xdevice modules
+ # 当前脚本运行的绝对路径 去掉最后两个路径
+ # 变量注释 framework_src_dir = OpenHarmony/test/developertest
sys.framework_src_dir = os.path.abspath(os.path.dirname(
os.path.dirname(__file__)))
+
+ # 将目录存放到sys.path模块中,新添加的目录会优先于其他目录被import检查 0代表最高优先级
sys.path.insert(0, sys.framework_src_dir)
+
+ # 当前脚本运行的绝对路径 去掉最后两个路径
+ # 变量注释 framework_root_dir = OpenHarmony/test/developertest
sys.framework_root_dir = os.path.abspath(os.path.dirname(
os.path.dirname(os.path.dirname(__file__))))
+ # 变量注释 sys.xdevice_dir = OpenHarmony/test/xdevice/src
sys.xdevice_dir = os.path.abspath(os.path.join(
sys.framework_root_dir,
"..",
@@ -35,6 +43,7 @@ def _init_global_config():
"src"))
sys.path.insert(0, sys.xdevice_dir)
+ # 变量注释 sys.xdevice_extension_dir = OpenHarmony/xdevice/extension/src
sys.xdevice_extension_dir = os.path.abspath(os.path.join(
sys.framework_root_dir,
"..",
@@ -43,12 +52,14 @@ def _init_global_config():
"src"))
sys.path.insert(1, sys.xdevice_extension_dir)
+ # 变量注释 pytest_dir = OpenHarmony/test/developertest/aw/python
sys.pytest_dir = os.path.abspath(os.path.join(
sys.framework_root_dir,
"aw",
"python"))
sys.path.insert(2, sys.pytest_dir)
+ # 变量注释 adapter_dir = OpenHarmony/test/developertest/adapter/aw/python
sys.adapter_dir = os.path.abspath(os.path.join(
sys.framework_root_dir,
"adapter"
@@ -56,18 +67,23 @@ def _init_global_config():
"python"))
sys.path.insert(3, sys.adapter_dir)
+ # 变量注释 hmh_script = OpenHarmony/test/developertest/libs
sys.hmh_script = os.path.abspath(os.path.join(
sys.framework_root_dir,
"libs"))
sys.path.insert(4, sys.hmh_script)
+ # 变量注释 framework_res_dir = OpenHarmony/test/developertest
sys.framework_res_dir = sys.framework_root_dir
+
+ # 变量注释 exec_dir = OpenHarmony/test/developertest
sys.exec_dir = sys.framework_root_dir
from core.common import get_source_code_root_path
sys.source_code_root_path = get_source_code_root_path(
sys.framework_root_dir)
+ # python的参数配置 设置脚本路径 调度python的xdevice
from xdevice import Variables
Variables.exec_dir = sys.framework_root_dir
@@ -76,6 +92,8 @@ def _iter_module_plugins(packages):
import importlib
import pkgutil
for package in packages:
+
+ # 获取__path__对象属性的值,若不存在,默认为“”
pkg_path = getattr(package, "__path__", "")
pkg_name = getattr(package, "__name__", "")
if not pkg_name or not pkg_path: