kopia lustrzana https://github.com/espressif/esp-idf
test: support loadable elf test cases:
loadable elf example is different for 2 reasons: 1. loadable elf binary don't have flasher_args.json, so we can't use normal to get from CI artifacts 2. it don't have binary and don't need to downloaded binary to DUT. Some related functions can be ignoredpull/4494/head
rodzic
cca08b3d2b
commit
164e8ba21f
|
@ -121,12 +121,13 @@ class SerialThread(object):
|
|||
@ttfw_idf.idf_example_test(env_tag="test_jtag_arm")
|
||||
def test_examples_loadable_elf(env, extra_data):
|
||||
|
||||
idf_path = os.environ['IDF_PATH']
|
||||
rel_project_path = os.path.join('examples', 'get-started', 'hello_world')
|
||||
app_files = ['hello-world.elf', 'partition_table/partition-table.bin']
|
||||
example = ttfw_idf.LoadableElfExample(rel_project_path, app_files, target="esp32")
|
||||
idf_path = example.get_sdk_path()
|
||||
proj_path = os.path.join(idf_path, rel_project_path)
|
||||
example = ttfw_idf.Example(rel_project_path, target="esp32")
|
||||
sdkconfig = example.get_sdkconfig()
|
||||
elf_path = os.path.join(example.get_binary_path(rel_project_path), 'hello-world.elf')
|
||||
elf_path = os.path.join(example.binary_path, 'hello-world.elf')
|
||||
esp_log_path = os.path.join(proj_path, 'esp.log')
|
||||
|
||||
assert(sdkconfig['CONFIG_IDF_TARGET_ESP32'] == 'y'), "Only ESP32 target is supported"
|
||||
|
|
|
@ -33,8 +33,9 @@ def parse_flash_settings(path):
|
|||
# CMake version using build metadata file
|
||||
with open(path, "r") as f:
|
||||
args = json.load(f)
|
||||
flash_files = [(offs, binary) for (offs, binary) in args["flash_files"].items() if offs != ""]
|
||||
flash_settings = args["flash_settings"]
|
||||
flash_files = [(offs, binary) for (offs, binary) in args["flash_files"].items() if offs != ""]
|
||||
flash_settings = args["flash_settings"]
|
||||
app_name = os.path.splitext(args["app"]["file"])[0]
|
||||
else:
|
||||
# GNU Make version uses download.config arguments file
|
||||
with open(path, "r") as f:
|
||||
|
@ -48,14 +49,28 @@ def parse_flash_settings(path):
|
|||
else:
|
||||
# offs, filename
|
||||
flash_files.append((args[idx], args[idx + 1]))
|
||||
return flash_files, flash_settings
|
||||
# we can only guess app name in download.config.
|
||||
for p in flash_files:
|
||||
if not os.path.dirname(p[1]) and "partition" not in p[1]:
|
||||
# app bin usually in the same dir with download.config and it's not partition table
|
||||
app_name = os.path.splitext(p[1])[0]
|
||||
break
|
||||
else:
|
||||
app_name = None
|
||||
return flash_files, flash_settings, app_name
|
||||
|
||||
|
||||
class Artifacts(object):
|
||||
def __init__(self, dest_root_path):
|
||||
def __init__(self, dest_root_path, artifact_index_file, app_path, config_name, target):
|
||||
assert gitlab_api
|
||||
# at least one of app_path or config_name is not None. otherwise we can't match artifact
|
||||
assert app_path or config_name
|
||||
assert os.path.exists(artifact_index_file)
|
||||
self.gitlab_inst = gitlab_api.Gitlab(os.getenv("CI_PROJECT_ID"))
|
||||
self.dest_root_path = dest_root_path
|
||||
with open(artifact_index_file, "r") as f:
|
||||
artifact_index = json.load(f)
|
||||
self.artifact_info = self._find_artifact(artifact_index, app_path, config_name, target)
|
||||
|
||||
@staticmethod
|
||||
def _find_artifact(artifact_index, app_path, config_name, target):
|
||||
|
@ -74,21 +89,13 @@ class Artifacts(object):
|
|||
ret = None
|
||||
return ret
|
||||
|
||||
def download_artifact(self, artifact_index_file, app_path, config_name, target):
|
||||
# at least one of app_path or config_name is not None. otherwise we can't match artifact
|
||||
assert app_path or config_name
|
||||
assert os.path.exists(artifact_index_file)
|
||||
with open(artifact_index_file, "r") as f:
|
||||
artifact_index = json.load(f)
|
||||
|
||||
artifact_info = self._find_artifact(artifact_index, app_path, config_name, target)
|
||||
|
||||
if artifact_info:
|
||||
base_path = os.path.join(artifact_info["work_dir"], artifact_info["build_dir"])
|
||||
job_id = artifact_info["ci_job_id"]
|
||||
def download_artifacts(self):
|
||||
if self.artifact_info:
|
||||
base_path = os.path.join(self.artifact_info["work_dir"], self.artifact_info["build_dir"])
|
||||
job_id = self.artifact_info["ci_job_id"]
|
||||
|
||||
# 1. download flash args file
|
||||
if artifact_info["build_system"] == "cmake":
|
||||
if self.artifact_info["build_system"] == "cmake":
|
||||
flash_arg_file = os.path.join(base_path, "flasher_args.json")
|
||||
else:
|
||||
flash_arg_file = os.path.join(base_path, "download.config")
|
||||
|
@ -96,14 +103,10 @@ class Artifacts(object):
|
|||
self.gitlab_inst.download_artifact(job_id, [flash_arg_file], self.dest_root_path)
|
||||
|
||||
# 2. download all binary files
|
||||
flash_files, flash_settings = parse_flash_settings(os.path.join(self.dest_root_path, flash_arg_file))
|
||||
artifact_files = []
|
||||
for p in flash_files:
|
||||
artifact_files.append(os.path.join(base_path, p[1]))
|
||||
if not os.path.dirname(p[1]):
|
||||
# find app bin and also download elf
|
||||
elf_file = os.path.splitext(p[1])[0] + ".elf"
|
||||
artifact_files.append(os.path.join(base_path, elf_file))
|
||||
flash_files, flash_settings, app_name = parse_flash_settings(os.path.join(self.dest_root_path,
|
||||
flash_arg_file))
|
||||
artifact_files = [os.path.join(base_path, p[1]) for p in flash_files]
|
||||
artifact_files.append(os.path.join(base_path, app_name + ".elf"))
|
||||
|
||||
self.gitlab_inst.download_artifact(job_id, artifact_files, self.dest_root_path)
|
||||
|
||||
|
@ -114,6 +117,22 @@ class Artifacts(object):
|
|||
base_path = None
|
||||
return base_path
|
||||
|
||||
def download_artifact_files(self, file_names):
|
||||
if self.artifact_info:
|
||||
base_path = os.path.join(self.artifact_info["work_dir"], self.artifact_info["build_dir"])
|
||||
job_id = self.artifact_info["ci_job_id"]
|
||||
|
||||
# download all binary files
|
||||
artifact_files = [os.path.join(base_path, fn) for fn in file_names]
|
||||
self.gitlab_inst.download_artifact(job_id, artifact_files, self.dest_root_path)
|
||||
|
||||
# download sdkconfig file
|
||||
self.gitlab_inst.download_artifact(job_id, [os.path.join(os.path.dirname(base_path), "sdkconfig")],
|
||||
self.dest_root_path)
|
||||
else:
|
||||
base_path = None
|
||||
return base_path
|
||||
|
||||
|
||||
class IDFApp(App.BaseApp):
|
||||
"""
|
||||
|
@ -132,24 +151,22 @@ class IDFApp(App.BaseApp):
|
|||
self.binary_path = self.get_binary_path(app_path, config_name, target)
|
||||
self.elf_file = self._get_elf_file_path(self.binary_path)
|
||||
assert os.path.exists(self.binary_path)
|
||||
sdkconfig_dict = self.get_sdkconfig()
|
||||
if "CONFIG_APP_BUILD_GENERATE_BINARIES" in sdkconfig_dict:
|
||||
# There are no flashing targets available when no binaries where generated.
|
||||
if self.IDF_DOWNLOAD_CONFIG_FILE not in os.listdir(self.binary_path):
|
||||
if self.IDF_FLASH_ARGS_FILE not in os.listdir(self.binary_path):
|
||||
msg = ("Neither {} nor {} exists. "
|
||||
"Try to run 'make print_flash_cmd | tail -n 1 > {}/{}' "
|
||||
"or 'idf.py build' "
|
||||
"for resolving the issue."
|
||||
"").format(self.IDF_DOWNLOAD_CONFIG_FILE, self.IDF_FLASH_ARGS_FILE,
|
||||
self.binary_path, self.IDF_DOWNLOAD_CONFIG_FILE)
|
||||
raise AssertionError(msg)
|
||||
if self.IDF_DOWNLOAD_CONFIG_FILE not in os.listdir(self.binary_path):
|
||||
if self.IDF_FLASH_ARGS_FILE not in os.listdir(self.binary_path):
|
||||
msg = ("Neither {} nor {} exists. "
|
||||
"Try to run 'make print_flash_cmd | tail -n 1 > {}/{}' "
|
||||
"or 'idf.py build' "
|
||||
"for resolving the issue."
|
||||
"").format(self.IDF_DOWNLOAD_CONFIG_FILE, self.IDF_FLASH_ARGS_FILE,
|
||||
self.binary_path, self.IDF_DOWNLOAD_CONFIG_FILE)
|
||||
raise AssertionError(msg)
|
||||
|
||||
self.flash_files, self.flash_settings = self._parse_flash_download_config()
|
||||
self.partition_table = self._parse_partition_table()
|
||||
self.flash_files, self.flash_settings = self._parse_flash_download_config()
|
||||
self.partition_table = self._parse_partition_table()
|
||||
|
||||
@classmethod
|
||||
def get_sdk_path(cls):
|
||||
# type: () -> str
|
||||
idf_path = os.getenv("IDF_PATH")
|
||||
assert idf_path
|
||||
assert os.path.exists(idf_path)
|
||||
|
@ -184,6 +201,7 @@ class IDFApp(App.BaseApp):
|
|||
return d
|
||||
|
||||
def get_binary_path(self, app_path, config_name=None, target=None):
|
||||
# type: (str, str, str) -> str
|
||||
"""
|
||||
get binary path according to input app_path.
|
||||
|
||||
|
@ -223,7 +241,7 @@ class IDFApp(App.BaseApp):
|
|||
# GNU Make version uses download.config arguments file
|
||||
path = os.path.join(self.binary_path, self.IDF_DOWNLOAD_CONFIG_FILE)
|
||||
|
||||
flash_files, flash_settings = parse_flash_settings(path)
|
||||
flash_files, flash_settings, app_name = parse_flash_settings(path)
|
||||
# The build metadata file does not currently have details, which files should be encrypted and which not.
|
||||
# Assume that all files should be encrypted if flash encryption is enabled in development mode.
|
||||
sdkconfig_dict = self.get_sdkconfig()
|
||||
|
@ -292,7 +310,7 @@ class Example(IDFApp):
|
|||
"""
|
||||
return [os.path.join(self.binary_path, "..", "sdkconfig")]
|
||||
|
||||
def get_binary_path(self, app_path, config_name=None, target=None):
|
||||
def _try_get_binary_from_local_fs(self, app_path, config_name=None, target=None):
|
||||
# build folder of example path
|
||||
path = os.path.join(self.idf_path, app_path, "build")
|
||||
if os.path.exists(path):
|
||||
|
@ -309,20 +327,52 @@ class Example(IDFApp):
|
|||
example_path = os.path.join(self.idf_path, "build_examples")
|
||||
for dirpath in os.listdir(example_path):
|
||||
if os.path.basename(dirpath) == app_path_underscored:
|
||||
path = os.path.join(example_path, dirpath, config_name, self.target, "build")
|
||||
path = os.path.join(example_path, dirpath, config_name, target, "build")
|
||||
if os.path.exists(path):
|
||||
return path
|
||||
else:
|
||||
# app path exists, but config name not exists. try to download artifacts.
|
||||
break
|
||||
return None
|
||||
|
||||
artifacts = Artifacts(self.idf_path)
|
||||
path = artifacts.download_artifact(CIAssignExampleTest.ARTIFACT_INDEX_FILE,
|
||||
app_path, config_name, target)
|
||||
def get_binary_path(self, app_path, config_name=None, target=None):
|
||||
path = self._try_get_binary_from_local_fs(app_path, config_name, target)
|
||||
if path:
|
||||
return os.path.join(self.idf_path, path)
|
||||
return path
|
||||
else:
|
||||
raise OSError("Failed to find example binary")
|
||||
artifacts = Artifacts(self.idf_path, CIAssignExampleTest.ARTIFACT_INDEX_FILE,
|
||||
app_path, config_name, target)
|
||||
path = artifacts.download_artifacts()
|
||||
if path:
|
||||
return os.path.join(self.idf_path, path)
|
||||
else:
|
||||
raise OSError("Failed to find example binary")
|
||||
|
||||
|
||||
class LoadableElfExample(Example):
|
||||
def __init__(self, app_path, app_files, config_name=None, target=None):
|
||||
# add arg `app_files` for loadable elf example.
|
||||
# Such examples only build elf files, so it doesn't generate flasher_args.json.
|
||||
# So we can't get app files from config file. Test case should pass it to application.
|
||||
super(IDFApp, self).__init__(app_path)
|
||||
self.app_files = app_files
|
||||
self.config_name = config_name
|
||||
self.target = target
|
||||
self.idf_path = self.get_sdk_path()
|
||||
self.binary_path = self.get_binary_path(app_path, config_name, target)
|
||||
self.elf_file = self._get_elf_file_path(self.binary_path)
|
||||
assert os.path.exists(self.binary_path)
|
||||
|
||||
def get_binary_path(self, app_path, config_name=None, target=None):
|
||||
path = self._try_get_binary_from_local_fs(app_path, config_name, target)
|
||||
if path:
|
||||
return path
|
||||
else:
|
||||
artifacts = Artifacts(self.idf_path, CIAssignExampleTest.ARTIFACT_INDEX_FILE,
|
||||
app_path, config_name, target)
|
||||
path = artifacts.download_artifact_files(self.app_files)
|
||||
if path:
|
||||
return os.path.join(self.idf_path, path)
|
||||
else:
|
||||
raise OSError("Failed to find example binary")
|
||||
|
||||
|
||||
class UT(IDFApp):
|
||||
|
|
|
@ -15,7 +15,7 @@ import os
|
|||
import re
|
||||
|
||||
from tiny_test_fw import TinyFW, Utility
|
||||
from IDFApp import IDFApp, Example, UT
|
||||
from IDFApp import IDFApp, Example, LoadableElfExample, UT # noqa: export all Apps for users
|
||||
from IDFDUT import IDFDUT, ESP32DUT, ESP32S2DUT, ESP8266DUT # noqa: export DUTs for users
|
||||
|
||||
|
||||
|
|
Ładowanie…
Reference in New Issue