As commit 6a1d9877ef ("cmake: Add LL_EXTENSION_BUILD to EDK flags")
made clear, only building an application with the EDK is not enough to
prevent regressions. This patch address that by also running the
application using the extension built with the EDK.
To provide a more comprehensive test, the application runs the extension
code on both kernel and user space, using a parameter sent by the
application. Assertions on the output from the application are used to
ensure expected results.
For now, tests only run on qemu_cortex_r5, but this can be expanded in
the future.
Signed-off-by: Ederson de Souza <ederson.desouza@intel.com>
114 lines
4.5 KiB
Python
114 lines
4.5 KiB
Python
# Copyright (c) 2024 Intel Corporation
|
|
#
|
|
# SPDX-License-Identifier: Apache-2.0
|
|
|
|
import logging
|
|
import os
|
|
import pytest
|
|
import shutil
|
|
import tempfile
|
|
|
|
from pathlib import Path
|
|
from subprocess import check_output
|
|
from twister_harness import DeviceAdapter
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
def test_edk(unlaunched_dut: DeviceAdapter):
|
|
# Need to have the ZEPHYR_SDK_INSTALL_DIR environment variable set,
|
|
# otherwise can't actually build the edk
|
|
if os.environ.get("ZEPHYR_SDK_INSTALL_DIR") is None:
|
|
logger.warning("ZEPHYR_SDK_INSTALL_DIR is not set, skipping test")
|
|
pytest.skip("ZEPHYR_SDK_INSTALL_DIR is not set")
|
|
|
|
# Can we build the edk?
|
|
command = [
|
|
"west",
|
|
"build",
|
|
"-b",
|
|
unlaunched_dut.device_config.platform,
|
|
"-t",
|
|
"llext-edk",
|
|
"--build-dir",
|
|
unlaunched_dut.device_config.build_dir,
|
|
]
|
|
output = check_output(command, text=True)
|
|
logger.info(output)
|
|
|
|
# Install the edk to a temporary location
|
|
with tempfile.TemporaryDirectory() as tempdir:
|
|
# Copy the edk to the temporary directory using python methods
|
|
logger.debug(f"Copying llext-edk.tar.xz to {tempdir}")
|
|
edk_path = Path(unlaunched_dut.device_config.build_dir) / "zephyr/llext-edk.tar.xz"
|
|
shutil.copy(edk_path, tempdir)
|
|
|
|
# Extract the edk using tar
|
|
logger.debug(f"Extracting llext-edk.tar.xz to {tempdir}")
|
|
command = ["tar", "-xf", "llext-edk.tar.xz"]
|
|
output = check_output(command, text=True, cwd=tempdir)
|
|
logger.info(output)
|
|
|
|
# Copy the extension to another temporary directory to test out of tree builds
|
|
with tempfile.TemporaryDirectory() as tempdir_extension:
|
|
logger.debug(f"Copying extension to {tempdir_extension}")
|
|
ext_dir = Path(os.environ["ZEPHYR_BASE"]) / "tests/misc/llext-edk/extension"
|
|
shutil.copytree(ext_dir, tempdir_extension, dirs_exist_ok=True)
|
|
|
|
# Also copy file2hex.py to the extension directory, so that it's possible
|
|
# to generate a hex file from the extension binary
|
|
logger.debug(f"Copying file2hex.py to {tempdir_extension}")
|
|
file2hex = Path(os.environ["ZEPHYR_BASE"]) / "scripts/build/file2hex.py"
|
|
shutil.copy(file2hex, tempdir_extension)
|
|
|
|
# Set the LLEXT_EDK_INSTALL_DIR environment variable so that the extension
|
|
# knows where the EDK is installed
|
|
edk_dir = Path(tempdir) / "llext-edk"
|
|
env = os.environ.copy()
|
|
env.update({"LLEXT_EDK_INSTALL_DIR": edk_dir})
|
|
|
|
# Build the extension using the edk
|
|
logger.debug(f"Building extension in {tempdir_extension} - cmake")
|
|
command = ["cmake", "-B", "build"]
|
|
output = check_output(command, text=True, cwd=tempdir_extension, env=env)
|
|
logger.info(output)
|
|
|
|
logger.debug(f"Building extension in {tempdir_extension} - make")
|
|
command = ["make", "-C", "build"]
|
|
output = check_output(command, text=True, cwd=tempdir_extension, env=env)
|
|
logger.info(output)
|
|
|
|
# Check if the extension was built
|
|
assert os.path.exists(Path(tempdir_extension) / "build/extension.llext")
|
|
|
|
# Can we run it? First, rebuild the application, now including the extension
|
|
# build directory in the include path, so that the application can find the
|
|
# extension code.
|
|
logger.debug(f"Running application with extension in {tempdir_extension} - west build")
|
|
command = [
|
|
"west",
|
|
"build",
|
|
"-b",
|
|
unlaunched_dut.device_config.platform,
|
|
"--build-dir",
|
|
unlaunched_dut.device_config.build_dir,
|
|
"--",
|
|
f"-DEXTENSION_DIR={tempdir_extension}/build/"
|
|
]
|
|
logger.debug(f"west command: {command}")
|
|
output = check_output(command, text=True)
|
|
logger.info(output)
|
|
|
|
# Now that the application is built, run it
|
|
logger.debug(f"Running application with extension in {tempdir_extension}")
|
|
try:
|
|
unlaunched_dut.launch()
|
|
lines = unlaunched_dut.readlines_until("Done")
|
|
|
|
assert "Calling extension from kernel" in lines
|
|
assert "Calling extension from user" in lines
|
|
assert "foo(42) is 1764" in lines
|
|
assert "foo(43) is 1849" in lines
|
|
|
|
finally:
|
|
unlaunched_dut.close()
|