Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

picolibc: tests with meson #254

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
281 changes: 150 additions & 131 deletions CMakeLists.txt

Large diffs are not rendered by default.

15 changes: 13 additions & 2 deletions cmake/meson-cross-build.txt.in
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
[binaries]
c = [@meson_c_args@]
c = [@meson_c_args@, '-nostdlib']
ar = '@LLVM_BINARY_DIR@/bin/llvm-ar@CMAKE_EXECUTABLE_SUFFIX@'
strip = '@LLVM_BINARY_DIR@/bin/llvm-strip@CMAKE_EXECUTABLE_SUFFIX@'
# only needed to run tests
exe_wrapper = ['sh', '-c', 'test -z "$PICOLIBC_TEST" || run-@cpu_family@ "$@"', 'run-@cpu_family@']
exe_wrapper = [
'sh',
'-c',
'test -z "$PICOLIBC_TEST" || @test_executor_bin@ "$@"',
'@test_executor_bin@',
@test_executor_params@]

[host_machine]
system = 'none'
Expand All @@ -13,3 +18,9 @@ endian = 'little'

[properties]
skip_sanity_check = true
libgcc ='-lclang_rt.builtins'
default_flash_addr = '@default_flash_addr@'
default_flash_size = '@default_flash_size@'
default_ram_addr = '@default_ram_addr@'
default_ram_size = '@default_ram_size@'
default_stack_size = '@default_stack_size@'
7 changes: 0 additions & 7 deletions test-support/ldscripts/picolibc_aarch64.ld

This file was deleted.

7 changes: 0 additions & 7 deletions test-support/ldscripts/picolibc_armv4t.ld

This file was deleted.

7 changes: 0 additions & 7 deletions test-support/ldscripts/picolibc_armv5te.ld

This file was deleted.

7 changes: 0 additions & 7 deletions test-support/ldscripts/picolibc_armv6m_soft_nofp.ld

This file was deleted.

7 changes: 0 additions & 7 deletions test-support/ldscripts/picolibc_armv7em_hard_fpv4_sp_d16.ld

This file was deleted.

7 changes: 0 additions & 7 deletions test-support/ldscripts/picolibc_armv7em_hard_fpv5_d16.ld

This file was deleted.

7 changes: 0 additions & 7 deletions test-support/ldscripts/picolibc_armv7em_soft_nofp.ld

This file was deleted.

7 changes: 0 additions & 7 deletions test-support/ldscripts/picolibc_armv7m_soft_nofp.ld

This file was deleted.

4 changes: 0 additions & 4 deletions test-support/ldscripts/picolibc_armv8.1m.main_hard_fp.ld

This file was deleted.

This file was deleted.

This file was deleted.

3 changes: 0 additions & 3 deletions test-support/ldscripts/picolibc_armv8m.main_hard_fp.ld

This file was deleted.

4 changes: 0 additions & 4 deletions test-support/ldscripts/picolibc_armv8m.main_soft_nofp.ld

This file was deleted.

59 changes: 13 additions & 46 deletions test-support/lit-exec-qemu.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,52 +6,10 @@
# (libc++abi, libunwind, libc++) and QEMU. It must handle the same command-line
# arguments as llvm-project/libcxx/utils/run.py.

import sys
from run_qemu import run_qemu
import argparse
import subprocess
import pathlib


def run(args):
"""Execute the program using QEMU and return the subprocess return code."""
qemu_params = ["-M", args.qemu_machine]
if args.qemu_cpu:
qemu_params += ["-cpu", args.qemu_cpu]
if args.qemu_params:
qemu_params += args.qemu_params.split(":")

# Setup semihosting with chardev bound to stdio.
# This is needed to test semihosting functionality in picolibc.
qemu_params += ["-chardev", "stdio,mux=on,id=stdio0"]
semihosting_config = ["enable=on", "chardev=stdio0"] + [
"arg=" + arg.replace(",", ",,") for arg in args.arguments
]
qemu_params += ["-semihosting-config", ",".join(semihosting_config)]

# Disable features we don't need and which could slow down the test or
# interfere with semihosting.
qemu_params += ["-monitor", "none", "-serial", "none", "-nographic"]

# Load the image to machine's memory and set the PC.
# "virt" machine cannot be used with load, as QEMU will try to put
# device tree blob at start of RAM conflicting with our code
# https://www.qemu.org/docs/master/system/arm/virt.html#hardware-configuration-information-for-bare-metal-programming
if args.qemu_machine == "virt":
qemu_params += ["-kernel", args.image]
else:
qemu_params += ["-device", f"loader,file={args.image},cpu-num=0"]

qemu_cmd = [args.qemu_command] + qemu_params
result = subprocess.run(
qemu_cmd,
stdout=subprocess.PIPE,
stderr=sys.stderr,
timeout=args.timeout,
cwd=args.execdir,
check=False,
)
sys.stdout.buffer.write(result.stdout)
return result.returncode
import sys


def main():
Expand Down Expand Up @@ -83,7 +41,7 @@ def main():
parser.add_argument(
"--execdir",
type=pathlib.Path,
default=".",
default=pathlib.Path.cwd(),
help="directory to run the program from",
)
parser.add_argument(
Expand All @@ -105,7 +63,16 @@ def main():
help="optional arguments for the image",
)
args = parser.parse_args()
ret_code = run(args)
ret_code = run_qemu(
args.qemu_command,
args.qemu_machine,
args.qemu_cpu,
args.qemu_params.split(":") if args.qemu_params else [],
args.image,
args.arguments,
args.timeout,
args.execdir,
)
sys.exit(ret_code)


Expand Down
96 changes: 96 additions & 0 deletions test-support/picolibc-test-wrapper.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
#!/usr/bin/env python3

# Copyright (c) 2023, Arm Limited and affiliates.

# This is a wrapper script to run picolibc tests with QEMU.

from run_qemu import run_qemu
import argparse
import pathlib
import sys

# https://mesonbuild.com/Unit-tests.html#skipped-tests-and-hard-errors
EXIT_CODE_SKIP = 77

disabled_tests = [
"picolibc_aarch64-build/test/math_errhandling",
"picolibc_armv7em_hard_fpv4_sp_d16-build/test/math_errhandling",
"picolibc_armv7em_hard_fpv5_d16-build/test/math_errhandling",
"picolibc_armv8m.main_hard_fp-build/test/printf_scanf",
"picolibc_armv8m.main_hard_fp-build/test/printff_scanff",
"picolibc_armv8m.main_hard_fp-build/test/printff-tests",
"picolibc_armv8m.main_hard_fp-build/test/math_errhandling",
"picolibc_armv8m.main_hard_fp-build/test/rounding-mode",
"picolibc_armv8m.main_hard_fp-build/test/long_double",
"picolibc_armv8m.main_hard_fp-build/test/rand",
"picolibc_armv8m.main_hard_fp-build/test/fenv",
"picolibc_armv8m.main_hard_fp-build/test/math-funcs",
"picolibc_armv8m.main_hard_fp-build/test/test-strtod",
"picolibc_armv8m.main_hard_fp-build/test/test-efcvt",
"picolibc_armv8m.main_hard_fp-build/test/complex-funcs",
"picolibc_armv8m.main_hard_fp-build/test/semihost/semihost-times",
"picolibc_armv8m.main_hard_fp-build/newlib/libm/test/math_test",
"picolibc_armv8m.main_hard_fp-build/test/libc-testsuite/sscanf",
"picolibc_armv8m.main_hard_fp-build/test/libc-testsuite/strtod",
"picolibc_armv8.1m.main_soft_nofp_nomve-build/newlib/libm/test/math_test",
"picolibc_armv8.1m.main_hard_fp-build/test/math_errhandling",
"picolibc_armv8.1m.main_hard_fp-build/newlib/libm/test/math_test",
"picolibc_armv8.1m.main_hard_nofp_mve-build/test/fenv",
"picolibc_armv8.1m.main_hard_nofp_mve-build/newlib/libm/test/math_test",
"picolibc_armv8.1m.main_hard_nofp_mve-build/test/math_errhandling",
]


def is_disabled(image):
return any([image.endswith(t) for t in disabled_tests])


def run(args):
if is_disabled(args.image):
return EXIT_CODE_SKIP
return run_qemu(
args.qemu_command,
args.qemu_machine,
args.qemu_cpu,
args.qemu_params.split(":") if args.qemu_params else [],
args.image,
args.arguments,
None,
pathlib.Path.cwd(),
)


def main():
parser = argparse.ArgumentParser(
description="Run a single test using qemu"
)
parser.add_argument(
"--qemu-command", required=True, help="qemu-system-<arch> path"
)
parser.add_argument(
"--qemu-machine",
required=True,
help="name of the machine to pass to QEMU",
)
parser.add_argument(
"--qemu-cpu", required=False, help="name of the cpu to pass to QEMU"
)
parser.add_argument(
"--qemu-params",
required=False,
help='list of arguments to pass to qemu, separated with ":"',
)
parser.add_argument("image", help="image file to execute")
parser.add_argument(
"arguments",
nargs=argparse.REMAINDER,
default=[],
help="optional arguments for the image",
)
args = parser.parse_args()
ret_code = run(args)
sys.exit(ret_code)


if __name__ == "__main__":
main()
61 changes: 61 additions & 0 deletions test-support/run_qemu.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
#!/usr/bin/env python3

# Copyright (c) 2023, Arm Limited and affiliates.

import subprocess
import sys


def run_qemu(
qemu_command,
qemu_machine,
qemu_cpu,
qemu_extra_params,
image,
arguments,
timeout,
working_directory,
):
"""Execute the program using QEMU and return the subprocess return code."""
qemu_params = ["-M", qemu_machine]
if qemu_cpu:
qemu_params += ["-cpu", qemu_cpu]
qemu_params += qemu_extra_params

# Setup semihosting with chardev bound to stdio.
# This is needed to test semihosting functionality in picolibc.
qemu_params += ["-chardev", "stdio,mux=on,id=stdio0"]
semihosting_config = ["enable=on", "chardev=stdio0"] + [
"arg=" + arg.replace(",", ",,") for arg in arguments
]
qemu_params += ["-semihosting-config", ",".join(semihosting_config)]

# Disable features we don't need and which could slow down the test or
# interfere with semihosting.
qemu_params += ["-monitor", "none", "-serial", "none", "-nographic"]

# Load the image to machine's memory and set the PC.
# "virt" machine cannot be used with load, as QEMU will try to put
# device tree blob at start of RAM conflicting with our code
# https://www.qemu.org/docs/master/system/arm/virt.html#hardware-configuration-information-for-bare-metal-programming
if qemu_machine == "virt":
qemu_params += ["-kernel", image]
else:
qemu_params += ["-device", f"loader,file={image},cpu-num=0"]

print(qemu_params)
sys.stdout.flush()

# setting stdin to devnull prevents qemu from fiddling with the echo bit of
# the parent terminal
result = subprocess.run(
[qemu_command] + qemu_params,
stdin=subprocess.DEVNULL,
stdout=subprocess.PIPE,
stderr=sys.stderr,
timeout=timeout,
cwd=working_directory,
check=False,
)
sys.stdout.buffer.write(result.stdout)
return result.returncode