zephyr/tests/misc/llext-edk/pytest/test_edk.py
Ederson de Souza fe573ebec6 tests/misc/llext-edk: Do run the test, instead of only building it
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>
2024-08-14 09:15:40 -04:00

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()