mirror of
https://github.com/openharmony/third_party_ltp.git
synced 2026-07-01 12:25:45 -04:00
ltp version update to 20250930
Signed-off-by: ccdu <duchangcheng1@h-partners.com>
This commit is contained in:
@@ -0,0 +1,9 @@
|
||||
# Configuration for the `b4` tool
|
||||
# See https://b4.docs.kernel.org/en/latest/config.html
|
||||
[b4]
|
||||
send-series-to = Linux Test Project <ltp@lists.linux.it>
|
||||
pw-url = https://patchwork.ozlabs.org/
|
||||
pw-project = ltp
|
||||
prep-perpatch-check-cmd = ./scripts/checkpatch.pl -q --terse --no-summary --mailback --showfile --no-tree --ignore CONST_STRUCT,VOLATILE,SPLIT_STRING,FILE_PATH_CHANGES
|
||||
am-perpatch-check-cmd = ./scripts/checkpatch.pl -q --terse --no-summary --mailback --no-tree --ignore CONST_STRUCT,VOLATILE,SPLIT_STRING,FILE_PATH_CHANGES
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
Containerfile
|
||||
@@ -1,2 +1,3 @@
|
||||
Petr Vorel <pvorel@suse.cz> <petr.vorel@gmail.com>
|
||||
Petr Vorel <pvorel@suse.cz> <pevik@users.noreply.github.com>
|
||||
Xinjian Ma (Fujitsu) <maxj.fnst@fujitsu.com> <maxj.fnst@fujitsu.com>
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
version: 2
|
||||
|
||||
build:
|
||||
os: "ubuntu-24.04"
|
||||
tools:
|
||||
python: "3.12"
|
||||
apt_packages:
|
||||
- autoconf
|
||||
- enchant-2
|
||||
- hunspell-en-us
|
||||
- make
|
||||
jobs:
|
||||
# Doc requires to have ltp.json
|
||||
pre_build:
|
||||
- make autotools
|
||||
- ./configure
|
||||
- make -C metadata/
|
||||
|
||||
# Build from the doc/ directory with Sphinx
|
||||
sphinx:
|
||||
configuration: doc/conf.py
|
||||
|
||||
# Explicitly set the version of Python and its requirements
|
||||
python:
|
||||
install:
|
||||
- requirements: doc/requirements.txt
|
||||
@@ -0,0 +1,35 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
# Copyright (c) 2023 SUSE LLC
|
||||
|
||||
ARG PREFIX=docker.io/
|
||||
ARG DISTRO_NAME=alpine
|
||||
ARG DISTRO_RELEASE=3.18
|
||||
|
||||
FROM $PREFIX$DISTRO_NAME:$DISTRO_RELEASE AS build
|
||||
ARG LTPROOT=/opt/ltp
|
||||
ARG DISTRO_NAME=alpine
|
||||
ARG DISTRO_RELEASE=3.18
|
||||
|
||||
RUN mkdir /build
|
||||
WORKDIR /build
|
||||
COPY . /build
|
||||
RUN ./ci/${DISTRO_NAME}.sh
|
||||
RUN git clean -fdX
|
||||
RUN ./build.sh -p $LTPROOT -i
|
||||
|
||||
FROM $PREFIX$DISTRO_NAME:$DISTRO_RELEASE
|
||||
ARG LTPROOT=/opt/ltp
|
||||
ARG KIRKROOT=/opt/kirk
|
||||
ARG DISTRO_NAME=alpine
|
||||
|
||||
COPY --from=build /build/ci/${DISTRO_NAME}-runtime.sh $LTPROOT/runtime-deps.sh
|
||||
RUN $LTPROOT/runtime-deps.sh
|
||||
|
||||
COPY --from=build $LTPROOT $LTPROOT
|
||||
ENV LTPROOT=$LTPROOT
|
||||
ENV PATH=$LTPROOT/testcases/bin:$LTPROOT/bin:$PATH
|
||||
|
||||
RUN mkdir -p $KIRKROOT
|
||||
COPY --from=build /build/tools/kirk $KIRKROOT
|
||||
|
||||
USER ltp
|
||||
@@ -55,13 +55,10 @@ in the same directory where the source files reside.
|
||||
$ make all
|
||||
$ make \
|
||||
"DESTDIR=$SYSROOT" \
|
||||
SKIP_IDCHECK=[0|1] \
|
||||
install
|
||||
|
||||
- Specifying DESTDIR is optional, but required when installing to a non-host
|
||||
sysroot, as opposed to the host system's sysroot.
|
||||
- Specify SKIP_IDCHECK=1 if and when you don't want to modify /etc/{group,passwd}
|
||||
on the target system's sysroot.
|
||||
|
||||
If you get a build error, please report it to ltp@lists.linux.it with
|
||||
following information,
|
||||
@@ -95,13 +92,10 @@ items which need fixing in the LTP tree.
|
||||
"top_srcdir=$TOP_SRCDIR" \
|
||||
"top_builddir=$OUT_OF_BUILD_TREE_DIR" \
|
||||
"DESTDIR=$SYSROOT" \
|
||||
SKIP_IDCHECK=[0|1]
|
||||
install
|
||||
|
||||
- Specifying DESTDIR is optional, but required when installing to a non-host
|
||||
sysroot, as opposed to the host system's sysroot.
|
||||
- Specify SKIP_IDCHECK=1 if and when you don't want to modify /etc/{group,passwd}
|
||||
on the target system's sysroot.
|
||||
|
||||
Quick Start
|
||||
-----------
|
||||
@@ -143,13 +137,7 @@ contributions are welcome.
|
||||
3. Build and install everything, as described above. Note the minimum software
|
||||
requirements above before doing so.
|
||||
|
||||
4. The disk I/O tests can be run by executing the diskio.sh script. In order
|
||||
for these tests to successfully operate a writable high-density 3.5" floppy
|
||||
must be in the disk drive and a CD-ROM with more than 100Mb of data must be
|
||||
in the CD-ROM drive. The corresponding tests will fail if either disk is
|
||||
missing.
|
||||
|
||||
5. The network tests related installation see testcases/network/README.md.
|
||||
4. The network tests related installation see testcases/network/README.md.
|
||||
|
||||
Cross compiling
|
||||
---------------
|
||||
@@ -177,6 +165,22 @@ PKG_CONFIG_LIBDIR=/usr/lib/i386-linux-gnu/pkgconfig CFLAGS=-m32 LDFLAGS=-m32 ./c
|
||||
* Arch Linux
|
||||
PKG_CONFIG_LIBDIR=/usr/lib32/pkgconfig CFLAGS=-m32 LDFLAGS=-m32 ./configure
|
||||
|
||||
Kernel modules
|
||||
--------------
|
||||
|
||||
LTP contains few kernel modules and tests which are using them.
|
||||
These require to be built with the same kernel headers as the running kernel (SUT).
|
||||
Sometimes the best way to achieve this is to compile them on the SUT.
|
||||
|
||||
Due Linux Kernel Driver Interface unstability [1], error during building kernel
|
||||
modules does not break the build. Make errors fatal can be done by FORCE_MODULES=1
|
||||
make variable.
|
||||
|
||||
'modules', 'modules-clean' and 'modules-install' make targets are shortcuts
|
||||
to build just these modules and tests.
|
||||
|
||||
[1] https://docs.kernel.org/process/stable-api-nonsense.html
|
||||
|
||||
Android Users
|
||||
-------------
|
||||
|
||||
@@ -202,47 +206,4 @@ LDLIBS - libraries listed after objects during link, e.g. -lc, -lpthread,
|
||||
-lltp.
|
||||
|
||||
For other variables and more info about the build systems see
|
||||
doc/build-system-guide.txt.
|
||||
|
||||
Common Issues
|
||||
-------------
|
||||
|
||||
Issue: When executing configure it says:
|
||||
|
||||
checking for a BSD-compatible install... /usr/bin/install -c
|
||||
checking whether build environment is sane... yes
|
||||
checking for gawk... gawk
|
||||
checking whether make sets $(MAKE)... yes
|
||||
configure: error: cannot run /bin/sh ./config.sub
|
||||
|
||||
Solution: You must upgrade autoconf to 0.10.2+ and m4 to 1.4.7+; config.guess and config.sub aren't necessarily generated with older revisions of the Gnu autotools chain.
|
||||
|
||||
Issue: When executing make [all] it says:
|
||||
|
||||
" *** No rule to make target `/$*', needed by `pan-all'. Stop."
|
||||
|
||||
Solution: You must upgrade to make 3.81. Please see the Requirements section above.
|
||||
|
||||
Issue: When executing make [all] it says something like:
|
||||
|
||||
# ...
|
||||
install -m 00644 "/scratch/ltp-dev2/ltp/include/test.h" "/scratch/ltp-install12/include/test.h"
|
||||
install -m 00644 "/scratch/ltp-dev2/ltp/include/tlibio.h" "/scratch/ltp-install12/include/tlibio.h"
|
||||
install -m 00644 "/scratch/ltp-dev2/ltp/include/usctest.h" "/scratch/ltp-install12/include/usctest.h"
|
||||
install -m 00644 "/scratch/ltp-dev2/ltp/include/write_log.h" "/scratch/ltp-install12/include/write_log.h"
|
||||
make[1]: Leaving directory `/scratch/ltp-dev2/ltp/include'
|
||||
make -C lib -f "/scratch/ltp-dev2/ltp/lib/Makefile" all
|
||||
make[1]: Entering directory `/scratch/ltp-dev2/ltp/lib'
|
||||
" *** No rule to make target `dataascii.o', needed by `libltp.a'. Stop." # <-- the error
|
||||
|
||||
Solution: You cannot build LTP with -r / --no-builtin-rules and/or
|
||||
-R / --no-builtin-variables specified. LTP relies heavily on built-in
|
||||
implicit rules and variables to function properly.
|
||||
|
||||
Issue: When executing make (no target, 3.80), it does the following, and doesn't execute all:
|
||||
|
||||
#
|
||||
make -C testcases/realtime autotools
|
||||
make[1]: Entering directory `/scratch/ltp/testcases/realtime'
|
||||
autoheader
|
||||
make[1]: Leaving directory `/scratch/ltp/testcases/realtime'
|
||||
doc/developers/build_system.rst.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
# Copyright (c) Linux Test Project, 2009-2022
|
||||
# Copyright (c) Linux Test Project, 2009-2025
|
||||
# Copyright (c) Cisco Systems Inc., 2009-2010
|
||||
# Ngie Cooper, July 2009
|
||||
|
||||
@@ -13,7 +13,6 @@ top_srcdir ?= $(CURDIR)
|
||||
|
||||
include $(top_srcdir)/include/mk/env_pre.mk
|
||||
include $(top_srcdir)/include/mk/automake.mk
|
||||
include $(top_srcdir)/include/mk/gitignore.mk
|
||||
|
||||
.SUFFIXES:
|
||||
.SUFFIXES: .am .default .h .in .m4 .mk
|
||||
@@ -25,10 +24,6 @@ vpath %.in $(top_srcdir)/include
|
||||
vpath %.m4 $(top_srcdir)/m4
|
||||
vpath %.mk $(top_srcdir)/mk:$(top_srcdir)/mk/include
|
||||
|
||||
# User wants uclinux binaries?
|
||||
UCLINUX ?= 0
|
||||
export UCLINUX
|
||||
|
||||
# CLEAN_TARGETS: Targets which exist solely in clean.
|
||||
# COMMON_TARGETS: Targets which exist in all, clean, and install.
|
||||
# INSTALL_TARGETS: Targets which exist in clean and install (contains
|
||||
@@ -36,11 +31,7 @@ export UCLINUX
|
||||
# BOOTSTRAP_TARGETS: Directories required to bootstrap out-of-build-tree
|
||||
# support.
|
||||
|
||||
# We're not using uclinux based targets (default).
|
||||
ifneq ($(UCLINUX),1)
|
||||
COMMON_TARGETS := pan utils
|
||||
INSTALL_TARGETS := doc
|
||||
endif
|
||||
|
||||
define target_to_dir_dep_mapping
|
||||
ifeq ($$(filter %-clean,$(1)),) # not *-clean
|
||||
@@ -105,8 +96,8 @@ $(filter-out include-clean,$(CLEAN_TARGETS))::
|
||||
|
||||
# Just like everything depends on include-all / -install, we need to get rid
|
||||
# of include last to ensure that things won't be monkey screwed up. Only do
|
||||
# this if we're invoking clean or a subclean directly though.
|
||||
ifneq ($(filter clean,$(MAKECMDGOALS)),)
|
||||
# this if we're invoking clean, distclean or a subclean directly though.
|
||||
ifneq ($(filter clean distclean,$(MAKECMDGOALS)),)
|
||||
INCLUDE_CLEAN_RDEP_SUBJECT := $(CLEAN_TARGETS)
|
||||
else
|
||||
ifneq ($(filter %clean,$(MAKECMDGOALS)),)
|
||||
@@ -178,6 +169,9 @@ INSTALL_TARGETS += $(addprefix $(DESTDIR)/$(bindir)/,$(BINDIR_INSTALL_SCRIPTS))
|
||||
|
||||
$(INSTALL_TARGETS): $(INSTALL_DIR) $(DESTDIR)/$(bindir)
|
||||
|
||||
.PHONY: doc
|
||||
doc: metadata-all
|
||||
|
||||
.PHONY: check
|
||||
check: $(CHECK_TARGETS)
|
||||
|
||||
@@ -194,6 +188,7 @@ ifneq ($(build),$(host))
|
||||
$(error running tests on cross-compile build not supported)
|
||||
endif
|
||||
$(call _test)
|
||||
$(MAKE) test-shell-loader
|
||||
$(MAKE) test-metadata
|
||||
|
||||
test-c: lib-all
|
||||
@@ -208,17 +203,38 @@ ifneq ($(build),$(host))
|
||||
endif
|
||||
$(call _test,-s)
|
||||
|
||||
test-shell-loader: lib-all
|
||||
ifneq ($(build),$(host))
|
||||
$(error running tests on cross-compile build not supported)
|
||||
endif
|
||||
$(top_srcdir)/testcases/lib/run_tests.sh -b $(abs_builddir)
|
||||
|
||||
test-metadata: metadata-all
|
||||
$(MAKE) -C $(abs_srcdir)/metadata/ test
|
||||
$(MAKE) -C $(abs_srcdir)/metadata test
|
||||
|
||||
MODULE_DIRS := $(shell \
|
||||
dirname $$(grep -l 'include.*module\.mk' $$(find $(abs_srcdir)/testcases/ -type f -name 'Makefile')))
|
||||
|
||||
|
||||
.PHONY: modules modules-clean modules-install
|
||||
modules:
|
||||
@$(foreach dir,$(MODULE_DIRS),\
|
||||
echo "Build $(dir)";\
|
||||
$(MAKE) -C $(dir) || exit $$?; \
|
||||
)
|
||||
modules-clean:
|
||||
@$(foreach dir,$(MODULE_DIRS),\
|
||||
echo "Build $(dir)";\
|
||||
$(MAKE) -C $(dir) clean || exit $$?; \
|
||||
)
|
||||
modules-install: modules
|
||||
@$(foreach dir,$(MODULE_DIRS),\
|
||||
echo "Build $(dir)";\
|
||||
$(MAKE) -C $(dir) install || exit $$?; \
|
||||
)
|
||||
|
||||
## Help
|
||||
.PHONY: help
|
||||
help:
|
||||
@echo "Please read the Configuration section in $(top_srcdir)/INSTALL"
|
||||
@exit 1
|
||||
|
||||
## Menuconfig
|
||||
menuconfig:
|
||||
@$(SHELL) "$(top_srcdir)/ltpmenu"
|
||||
|
||||
## End misc targets.
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@
|
||||
"Name" : "ltp",
|
||||
"License" : "GPL V2.0",
|
||||
"License File" : "COPYING",
|
||||
"Version Number" : "20230929",
|
||||
"Version Number" : "20250930",
|
||||
"Owner" : "liuxun@huawei.com",
|
||||
"Upstream URL" : "https://github.com/linux-test-project/ltp",
|
||||
"Description" : "The LTP testsuite contains a collection of tools for testing the Linux kernel and related features."
|
||||
|
||||
@@ -1,213 +0,0 @@
|
||||
Linux Test Project
|
||||
==================
|
||||
|
||||
Linux Test Project is a joint project started by SGI, OSDL and Bull developed
|
||||
and maintained by IBM, Cisco, Fujitsu, SUSE, Red Hat, Oracle and others. The
|
||||
project goal is to deliver tests to the open source community that validate the
|
||||
reliability, robustness, and stability of Linux.
|
||||
|
||||
The LTP testsuite contains a collection of tools for testing the Linux kernel
|
||||
and related features. Our goal is to improve the Linux kernel and system
|
||||
libraries by bringing test automation to the testing effort. Interested open
|
||||
source contributors are encouraged to join.
|
||||
|
||||
Project pages are located at: http://linux-test-project.github.io/
|
||||
|
||||
The latest image is always available at:
|
||||
https://github.com/linux-test-project/ltp/releases
|
||||
|
||||
The discussion about the project happens at LTP mailing list:
|
||||
http://lists.linux.it/listinfo/ltp
|
||||
|
||||
LTP mailing list is archived at:
|
||||
https://lore.kernel.org/ltp/
|
||||
|
||||
IRC #ltp at: [irc.libera.chat](https://libera.chat/)
|
||||
|
||||
The git repository is located at GitHub at:
|
||||
https://github.com/linux-test-project/ltp
|
||||
|
||||
The patchwork instance is at:
|
||||
https://patchwork.ozlabs.org/project/ltp/list/
|
||||
|
||||
Warning!
|
||||
========
|
||||
|
||||
**Be careful with these tests!**
|
||||
|
||||
Don't run them on production systems. Growfiles, doio, and iogen in particular
|
||||
stress the I/O capabilities of systems and while they should not cause problems
|
||||
on properly functioning systems, they are intended to find (or cause) problems.
|
||||
|
||||
Quick guide to running the tests
|
||||
================================
|
||||
|
||||
If you have git, autoconf, automake, m4, pkgconf / pkg-config, libc headers,
|
||||
linux kernel headers and other common development packages installed (see
|
||||
INSTALL and ci/*.sh), the chances are the following will work:
|
||||
|
||||
```
|
||||
$ git clone https://github.com/linux-test-project/ltp.git
|
||||
$ cd ltp
|
||||
$ make autotools
|
||||
$ ./configure
|
||||
```
|
||||
|
||||
Now you can continue either with compiling and running a single test or with
|
||||
compiling and installing the whole testsuite.
|
||||
|
||||
For optional library dependencies look into scripts for major distros in
|
||||
`ci/` directory. You can also build whole LTP with `./build.sh` script.
|
||||
|
||||
Shortcut to running a single test
|
||||
---------------------------------
|
||||
If you need to execute a single test you actually do not need to compile
|
||||
the whole LTP, if you want to run a syscall testcase following should work.
|
||||
|
||||
```
|
||||
$ cd testcases/kernel/syscalls/foo
|
||||
$ make
|
||||
$ PATH=$PATH:$PWD ./foo01
|
||||
```
|
||||
|
||||
Shell testcases are a bit more complicated since these need a path to a shell
|
||||
library as well as to compiled binary helpers, but generally following should
|
||||
work.
|
||||
|
||||
```
|
||||
$ cd testcases/lib
|
||||
$ make
|
||||
$ cd ../commands/foo
|
||||
$ PATH=$PATH:$PWD:$PWD/../../lib/ ./foo01.sh
|
||||
```
|
||||
|
||||
Open Posix Testsuite has it's own build system which needs Makefiles to be
|
||||
generated first, then compilation should work in subdirectories as well.
|
||||
|
||||
```
|
||||
$ cd testcases/open_posix_testsuite/
|
||||
$ make generate-makefiles
|
||||
$ cd conformance/interfaces/foo
|
||||
$ make
|
||||
$ ./foo_1-1.run-test
|
||||
```
|
||||
|
||||
Compiling and installing all testcases
|
||||
--------------------------------------
|
||||
|
||||
```
|
||||
$ make
|
||||
$ make install
|
||||
```
|
||||
|
||||
This will install LTP to `/opt/ltp`.
|
||||
* If you have a problem see `INSTALL` and `./configure --help`.
|
||||
* Failing that, ask for help on the mailing list or Github.
|
||||
|
||||
Some tests will be disabled if the configure script can not find their build
|
||||
dependencies.
|
||||
|
||||
* If a test returns `TCONF` due to a missing component, check the `./configure`
|
||||
output.
|
||||
* If a tests fails due to a missing user or group, see the Quick Start section
|
||||
of `INSTALL`.
|
||||
|
||||
Running tests
|
||||
-------------
|
||||
|
||||
To run all the test suites
|
||||
|
||||
```
|
||||
$ cd /opt/ltp
|
||||
$ ./runltp
|
||||
```
|
||||
|
||||
Note that many test cases have to be executed as root.
|
||||
|
||||
To run a particular test suite
|
||||
|
||||
```
|
||||
$ ./runltp -f syscalls
|
||||
```
|
||||
|
||||
To run all tests with `madvise` in the name
|
||||
|
||||
```
|
||||
$ ./runltp -f syscalls -s madvise
|
||||
```
|
||||
Also see
|
||||
|
||||
```
|
||||
$ ./runltp --help
|
||||
```
|
||||
|
||||
Test suites (e.g. syscalls) are defined in the runtest directory. Each file
|
||||
contains a list of test cases in a simple format, see doc/ltp-run-files.txt.
|
||||
|
||||
Each test case has its own executable or script, these can be executed
|
||||
directly
|
||||
|
||||
```
|
||||
$ testcases/bin/abort01
|
||||
```
|
||||
|
||||
Some have arguments
|
||||
|
||||
```
|
||||
$ testcases/bin/mesgq\_nstest -m none
|
||||
```
|
||||
|
||||
The vast majority of test cases accept the -h (help) switch
|
||||
|
||||
```
|
||||
$ testcases/bin/ioctl01 -h
|
||||
```
|
||||
|
||||
Many require certain environment variables to be set
|
||||
|
||||
```
|
||||
$ LTPROOT=/opt/ltp PATH="$PATH:$LTPROOT/testcases/bin" testcases/bin/wc01.sh
|
||||
```
|
||||
|
||||
Most commonly, the path variable needs to be set and also `LTPROOT`, but there
|
||||
are a number of other variables, `runltp` usually sets these for you.
|
||||
|
||||
Note that all shell scripts need the `PATH` to be set. However this is not
|
||||
limited to shell scripts, many C based tests need environment variables as
|
||||
well.
|
||||
|
||||
For more info see `doc/user-guide.txt` or online at
|
||||
https://github.com/linux-test-project/ltp/wiki/User-Guidelines.
|
||||
|
||||
Network tests
|
||||
-------------
|
||||
Network tests require certain setup, described in `testcases/network/README.md`
|
||||
(online at https://github.com/linux-test-project/ltp/tree/master/testcases/network).
|
||||
|
||||
Developers corner
|
||||
=================
|
||||
|
||||
Before you start you should read following documents:
|
||||
|
||||
* `doc/test-writing-guidelines.txt`
|
||||
* `doc/build-system-guide.txt`
|
||||
* `doc/library-api-writing-guidelines.txt`
|
||||
|
||||
There is also a step-by-step tutorial:
|
||||
|
||||
* `doc/c-test-tutorial-simple.txt`
|
||||
|
||||
If something is not covered there don't hesitate to ask on the LTP mailing
|
||||
list. Also note that these documents are available online at:
|
||||
|
||||
* https://github.com/linux-test-project/ltp/wiki/Test-Writing-Guidelines
|
||||
* https://github.com/linux-test-project/ltp/wiki/LTP-Library-API-Writing-Guidelines
|
||||
* https://github.com/linux-test-project/ltp/wiki/Build-System
|
||||
* https://github.com/linux-test-project/ltp/wiki/C-Test-Case-Tutorial
|
||||
|
||||
Although we accept GitHub pull requests, the preferred way is sending patches to our mailing list.
|
||||
|
||||
It's a good idea to test patches on GitHub Actions before posting to mailing
|
||||
list. Our GitHub Actions setup covers various architectures and distributions in
|
||||
order to make sure LTP compiles cleanly on most common configurations.
|
||||
For testing you need to just push your changes to your own LTP fork on GitHub.
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
Linux Test Project
|
||||
==================
|
||||
|
||||
Linux Test Project is a joint project started by SGI, OSDL and Bull developed
|
||||
and maintained by SUSE, Red Hat, Fujitsu, IBM, Cisco, Oracle and others. The
|
||||
project goal is to deliver tests to the open source community that validate
|
||||
reliability, robustness, and stability of the Linux Kernel.
|
||||
|
||||
The testing suites contain a collection of tools for testing the Linux kernel
|
||||
and related features. Our goal is to improve the Linux kernel and system
|
||||
libraries by bringing test automation.
|
||||
|
||||
.. warning::
|
||||
|
||||
LTP tests shouldn't run in production systems. In particular,
|
||||
growfiles, doio, and iogen, stress the I/O capabilities of the systems and
|
||||
they are intended to find (or cause) problems.
|
||||
|
||||
Some references:
|
||||
|
||||
* `Documentation <http://linux-test-project.rtfd.io/>`_
|
||||
* `Source code <https://github.com/linux-test-project/ltp>`_
|
||||
* `Releases <https://github.com/linux-test-project/ltp/releases>`_
|
||||
* `Mailing List <http://lists.linux.it/listinfo/ltp>`_
|
||||
* `Working patches (patchwork) <https://patchwork.ozlabs.org/project/ltp/list/>`_
|
||||
* `Working patches (lore.kernel.org) <https://lore.kernel.org/ltp>`_
|
||||
* `#ltp @ libera chat <https://libera.chat/>`_
|
||||
@@ -138,7 +138,7 @@ install_in_tree()
|
||||
install_out_tree()
|
||||
{
|
||||
cd $BUILD_DIR
|
||||
make $MAKE_OPTS_OUT_TREE DESTDIR="$prefix" SKIP_IDCHECK=1 install
|
||||
make $MAKE_OPTS_OUT_TREE DESTDIR="$prefix" install
|
||||
}
|
||||
|
||||
usage()
|
||||
@@ -173,13 +173,14 @@ cross cross-compile build (requires set compiler via -c switch)
|
||||
native native build
|
||||
|
||||
RUN:
|
||||
autotools run only 'make autotools'
|
||||
configure run only 'configure'
|
||||
build run only 'make'
|
||||
test run only 'make test' (not supported for cross-compile build)
|
||||
test-c run only 'make test-c' (not supported for cross-compile build)
|
||||
test-shell run only 'make test-shell' (not supported for cross-compile build)
|
||||
install run only 'make install'
|
||||
autotools run only 'make autotools'
|
||||
configure run only 'configure'
|
||||
build run only 'make'
|
||||
test run only 'make test' (not supported for cross-compile build)
|
||||
test-c run only 'make test-c' (not supported for cross-compile build)
|
||||
test-shell run only 'make test-shell' (not supported for cross-compile build)
|
||||
test-shell-loader run only 'make test-shell-loader' (not supported for cross-compile build)
|
||||
install run only 'make install'
|
||||
|
||||
Default configure options:
|
||||
in-tree: $CONFIGURE_OPTS_IN_TREE
|
||||
@@ -206,7 +207,7 @@ while getopts "c:hio:p:r:t:" opt; do
|
||||
esac;;
|
||||
p) prefix="$OPTARG";;
|
||||
r) case "$OPTARG" in
|
||||
autotools|configure|build|test|test-c|test-shell|install) run="$OPTARG";;
|
||||
autotools|configure|build|test|test-c|test-shell|test-shell-loader|install) run="$OPTARG";;
|
||||
*) echo "Wrong run type '$OPTARG'" >&2; usage; exit 1;;
|
||||
esac;;
|
||||
t) case "$OPTARG" in
|
||||
@@ -232,7 +233,7 @@ if [ -z "$run" -o "$run" = "build" ]; then
|
||||
eval build_${tree}_tree
|
||||
fi
|
||||
|
||||
if [ -z "$run" -o "$run" = "test" -o "$run" = "test-c" -o "$run" = "test-shell" ]; then
|
||||
if [ -z "$run" -o "$run" = "test" -o "$run" = "test-c" -o "$run" = "test-shell" -o "$run" = "test-shell-loader" ]; then
|
||||
if [ "$build" = "cross" ]; then
|
||||
echo "cross-compile build, skipping running tests" >&2
|
||||
else
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
#!/bin/sh -eux
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
# Copyright (c) 2023 SUSE LLC
|
||||
|
||||
apk add \
|
||||
acl \
|
||||
curl \
|
||||
jq \
|
||||
keyutils \
|
||||
libaio \
|
||||
libacl \
|
||||
libcap \
|
||||
libselinux \
|
||||
libsepol \
|
||||
libtirpc \
|
||||
numactl \
|
||||
openssl \
|
||||
py3-msgpack
|
||||
|
||||
adduser -D -g "Unprivileged LTP user" ltp
|
||||
+6
-8
@@ -1,21 +1,21 @@
|
||||
#!/bin/sh
|
||||
# Copyright (c) 2019-2022 Petr Vorel <petr.vorel@gmail.com>
|
||||
set -ex
|
||||
#!/bin/sh -eux
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
# Copyright (c) 2019-2024 Petr Vorel <petr.vorel@gmail.com>
|
||||
|
||||
apk update
|
||||
|
||||
apk add \
|
||||
acl-dev \
|
||||
asciidoc \
|
||||
asciidoctor \
|
||||
autoconf \
|
||||
automake \
|
||||
clang \
|
||||
curl \
|
||||
jq \
|
||||
gcc \
|
||||
git \
|
||||
acl-dev \
|
||||
keyutils-dev \
|
||||
libaio-dev \
|
||||
libacl \
|
||||
libcap-dev \
|
||||
libselinux-dev \
|
||||
libsepol-dev \
|
||||
@@ -25,7 +25,6 @@ apk add \
|
||||
musl-dev \
|
||||
numactl-dev \
|
||||
openssl-dev \
|
||||
perl-json \
|
||||
pkgconfig
|
||||
|
||||
cat /etc/os-release
|
||||
@@ -34,7 +33,6 @@ echo "WARNING: remove unsupported tests (until they're fixed)"
|
||||
cd $(dirname $0)/..
|
||||
rm -rfv \
|
||||
testcases/kernel/syscalls/fmtmsg/fmtmsg01.c \
|
||||
testcases/kernel/syscalls/rt_tgsigqueueinfo/rt_tgsigqueueinfo01.c \
|
||||
testcases/kernel/syscalls/timer_create/timer_create01.c \
|
||||
testcases/kernel/syscalls/timer_create/timer_create03.c
|
||||
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
fedora.sh
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/bin/sh
|
||||
#!/bin/sh -eux
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
# Copyright (c) 2018-2020 Petr Vorel <pvorel@suse.cz>
|
||||
set -ex
|
||||
|
||||
if [ -z "$ARCH" ]; then
|
||||
echo "missing \$ARCH!" >&2
|
||||
|
||||
+10
-8
@@ -1,20 +1,22 @@
|
||||
#!/bin/sh
|
||||
# Copyright (c) 2018-2020 Petr Vorel <pvorel@suse.cz>
|
||||
set -ex
|
||||
#!/bin/sh -eux
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
# Copyright (c) 2018-2024 Petr Vorel <pvorel@suse.cz>
|
||||
|
||||
dpkg --add-architecture i386
|
||||
apt update
|
||||
|
||||
apt install -y --no-install-recommends \
|
||||
curl \
|
||||
jq \
|
||||
linux-libc-dev:i386 \
|
||||
gcc-multilib \
|
||||
libacl1:i386 \
|
||||
libaio1:i386 \
|
||||
libcap2:i386 \
|
||||
libacl1-dev:i386 \
|
||||
libaio-dev:i386 \
|
||||
libcap-dev:i386 \
|
||||
libc6-dev-i386 \
|
||||
libc6:i386 \
|
||||
libkeyutils1:i386 \
|
||||
libnuma1:i386 \
|
||||
libkeyutils-dev:i386 \
|
||||
libnuma-dev:i386 \
|
||||
libssl-dev:i386 \
|
||||
libtirpc-dev:i386 \
|
||||
pkg-config:i386
|
||||
|
||||
+4
-20
@@ -1,21 +1,5 @@
|
||||
#!/bin/sh
|
||||
# Copyright (c) 2018-2023 Petr Vorel <pvorel@suse.cz>
|
||||
set -ex
|
||||
#!/bin/sh -eux
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
# Copyright (c) 2018-2024 Petr Vorel <pvorel@suse.cz>
|
||||
|
||||
apt="apt remove -y"
|
||||
|
||||
$apt \
|
||||
asciidoc \
|
||||
asciidoctor \
|
||||
libacl1-dev \
|
||||
libaio-dev \
|
||||
libaio1 \
|
||||
libcap-dev \
|
||||
libkeyutils-dev \
|
||||
libnuma-dev \
|
||||
libnuma1 \
|
||||
libselinux1-dev \
|
||||
libsepol-dev \
|
||||
libssl-dev
|
||||
|
||||
$apt asciidoc-base ruby-asciidoctor || true
|
||||
ACTION="remove-nonessential" $(dirname $0)/debian.sh
|
||||
|
||||
+51
-39
@@ -1,6 +1,6 @@
|
||||
#!/bin/sh
|
||||
# Copyright (c) 2018-2021 Petr Vorel <pvorel@suse.cz>
|
||||
set -ex
|
||||
#!/bin/sh -eux
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
# Copyright (c) 2018-2024 Petr Vorel <pvorel@suse.cz>
|
||||
|
||||
# workaround for missing oldstable-updates repository
|
||||
# W: Failed to fetch http://deb.debian.org/debian/dists/oldstable-updates/main/binary-amd64/Packages
|
||||
@@ -11,44 +11,56 @@ apt update
|
||||
# workaround for Ubuntu impish asking to interactively configure tzdata
|
||||
export DEBIAN_FRONTEND="noninteractive"
|
||||
|
||||
apt="apt install -y --no-install-recommends"
|
||||
install="apt install -y --no-install-recommends"
|
||||
remove="apt remove -y"
|
||||
|
||||
$apt \
|
||||
acl-dev \
|
||||
asciidoc \
|
||||
asciidoctor \
|
||||
autoconf \
|
||||
automake \
|
||||
build-essential \
|
||||
debhelper \
|
||||
devscripts \
|
||||
clang \
|
||||
gcc \
|
||||
git \
|
||||
iproute2 \
|
||||
libacl1 \
|
||||
libacl1-dev \
|
||||
libaio-dev \
|
||||
libaio1 \
|
||||
libcap-dev \
|
||||
libcap2 \
|
||||
libc6 \
|
||||
libc6-dev \
|
||||
libjson-perl \
|
||||
libkeyutils-dev \
|
||||
libkeyutils1 \
|
||||
libmnl-dev \
|
||||
libnuma-dev \
|
||||
libnuma1 \
|
||||
libselinux1-dev \
|
||||
libsepol-dev \
|
||||
libssl-dev \
|
||||
libtirpc-dev \
|
||||
linux-libc-dev \
|
||||
lsb-release \
|
||||
# libc6-dev and libtirpc-dev are hard dependencies for gcc toolchain
|
||||
# LTP should be compilable without linux-libc-dev, but we expect kernel headers.
|
||||
pkg_minimal="
|
||||
autoconf
|
||||
automake
|
||||
build-essential
|
||||
debhelper
|
||||
devscripts
|
||||
clang
|
||||
curl
|
||||
jq
|
||||
gcc
|
||||
git
|
||||
iproute2
|
||||
libc6-dev
|
||||
libtirpc-dev
|
||||
linux-libc-dev
|
||||
lsb-release
|
||||
pkg-config
|
||||
"
|
||||
|
||||
$apt ruby-asciidoctor-pdf || true
|
||||
$apt asciidoc-dblatex || true
|
||||
pkg_nonessential="
|
||||
acl-dev
|
||||
libacl1-dev
|
||||
libaio-dev
|
||||
libcap-dev
|
||||
libkeyutils-dev
|
||||
libnuma-dev
|
||||
libmnl-dev
|
||||
libselinux1-dev
|
||||
libsepol-dev
|
||||
libssl-dev
|
||||
"
|
||||
|
||||
case "$ACTION" in
|
||||
minimal)
|
||||
echo "=== Installing only minimal dependencies ==="
|
||||
$install $pkg_minimal
|
||||
;;
|
||||
remove-nonessential)
|
||||
echo "=== Make sure devel libraries are removed ==="
|
||||
$remove $pkg_nonessential
|
||||
;;
|
||||
*)
|
||||
echo "=== Installing dependencies ==="
|
||||
$install $pkg_minimal $pkg_nonessential
|
||||
;;
|
||||
esac
|
||||
|
||||
df -hT
|
||||
|
||||
+12
-7
@@ -1,15 +1,23 @@
|
||||
#!/bin/sh
|
||||
#!/bin/sh -eux
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
# Copyright (c) 2018-2021 Petr Vorel <pvorel@suse.cz>
|
||||
set -ex
|
||||
|
||||
yum="yum -y install --skip-broken"
|
||||
if command -v dnf5 >/dev/null 2>&1; then
|
||||
yum="dnf5 -y install --skip-broken --skip-unavailable"
|
||||
elif command -v dnf >/dev/null 2>&1; then
|
||||
yum="dnf -y install --skip-broken"
|
||||
else
|
||||
yum="yum -y install --skip-broken"
|
||||
fi
|
||||
|
||||
$yum \
|
||||
asciidoc \
|
||||
autoconf \
|
||||
automake \
|
||||
make \
|
||||
clang \
|
||||
gawk \
|
||||
curl \
|
||||
jq \
|
||||
gcc \
|
||||
git \
|
||||
findutils \
|
||||
@@ -17,11 +25,8 @@ $yum \
|
||||
numactl-devel \
|
||||
libtirpc \
|
||||
libtirpc-devel \
|
||||
perl-JSON \
|
||||
perl-libwww-perl \
|
||||
pkg-config \
|
||||
redhat-lsb-core
|
||||
|
||||
# CentOS 8 fixes
|
||||
$yum libmnl-devel || $yum libmnl
|
||||
$yum rubygem-asciidoctor || true
|
||||
|
||||
+46
-1
@@ -1 +1,46 @@
|
||||
tumbleweed.sh
|
||||
#!/bin/sh -eux
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
# Copyright (c) 2018-2025 Petr Vorel <pvorel@suse.cz>
|
||||
|
||||
zyp="zypper --non-interactive install --force-resolution --no-recommends"
|
||||
|
||||
i=10
|
||||
while [ $i != 0 ]; do
|
||||
$zyp \
|
||||
autoconf \
|
||||
automake \
|
||||
clang \
|
||||
curl \
|
||||
jq \
|
||||
findutils \
|
||||
gcc \
|
||||
git \
|
||||
gzip \
|
||||
iproute2 \
|
||||
make \
|
||||
kernel-default-devel \
|
||||
keyutils-devel \
|
||||
libacl-devel \
|
||||
libaio-devel \
|
||||
libcap-devel \
|
||||
libmnl-devel \
|
||||
libnuma-devel \
|
||||
libopenssl-devel \
|
||||
libselinux-devel \
|
||||
libtirpc-devel \
|
||||
linux-glibc-devel \
|
||||
lsb-release \
|
||||
pkg-config
|
||||
|
||||
ret=$?
|
||||
|
||||
if [ $ret -eq 106 ]; then
|
||||
echo "Broken repositories, try $i..."
|
||||
sleep 5
|
||||
i=$((i-1))
|
||||
continue
|
||||
fi
|
||||
break
|
||||
done
|
||||
|
||||
exit $ret
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
#!/bin/sh -eux
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
# Copyright (c) 2018-2021 Petr Vorel <pvorel@suse.cz>
|
||||
|
||||
if command -v dnf5 >/dev/null 2>&1; then
|
||||
yum="dnf5 -y install --skip-broken --skip-unavailable"
|
||||
elif command -v dnf >/dev/null 2>&1; then
|
||||
yum="dnf -y install --skip-broken"
|
||||
else
|
||||
yum="yum -y install --skip-broken"
|
||||
fi
|
||||
|
||||
$yum \
|
||||
autoconf \
|
||||
automake \
|
||||
make \
|
||||
clang \
|
||||
gawk \
|
||||
curl \
|
||||
jq \
|
||||
gcc \
|
||||
git \
|
||||
findutils \
|
||||
iproute \
|
||||
numactl-devel \
|
||||
libtirpc \
|
||||
libtirpc-devel \
|
||||
pkg-config \
|
||||
redhat-lsb-core
|
||||
|
||||
# CentOS 8 fixes
|
||||
$yum libmnl-devel || $yum libmnl
|
||||
@@ -0,0 +1,197 @@
|
||||
#!/bin/sh
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
#
|
||||
# Shell script to communicate with Patchwork via REST API.
|
||||
# It has been mainly created for CI purposes, but it can be used in the shell
|
||||
# by satisfying minimum requirements.
|
||||
#
|
||||
# Copyright (c) 2025 Andrea Cervesato <andrea.cervesato@suse.com>
|
||||
|
||||
PATCHWORK_URL="${PATCHWORK_URL:-https://patchwork.ozlabs.org}"
|
||||
PATCHWORK_SINCE="${PATCHWORK_SINCE:-3600}"
|
||||
|
||||
command_exists() {
|
||||
local cmd
|
||||
|
||||
for cmd in "$@"; do
|
||||
if ! command -v "$cmd" >/dev/null 2>&1; then
|
||||
echo "'$1' must be present in the system" >&2
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
command_exists "curl" "jq"
|
||||
|
||||
fetch_series() {
|
||||
local current_time=$(date +%s)
|
||||
local since_time=$(expr $current_time - $PATCHWORK_SINCE)
|
||||
local date=$(date -u -d @$since_time +"%Y-%m-%dT%H:%M:%SZ")
|
||||
local stdout
|
||||
|
||||
stdout=$(curl -k -G "$PATCHWORK_URL/api/events/" \
|
||||
--data "category=series-completed" \
|
||||
--data "project=ltp" \
|
||||
--data "state=new" \
|
||||
--data "since=$date" \
|
||||
--data "archive=no")
|
||||
|
||||
[ $? -eq 0 ] || exit 1
|
||||
|
||||
echo "$stdout" | jq -r '.[] | "\(.payload.series.id) \(.payload.series.mbox)"'
|
||||
}
|
||||
|
||||
get_patches() {
|
||||
local series_id="$1"
|
||||
local stdout
|
||||
|
||||
stdout="$(curl -k -G $PATCHWORK_URL/api/patches/ \
|
||||
--data project=ltp \
|
||||
--data series=$series_id)"
|
||||
|
||||
[ $? -eq 0 ] || exit 1
|
||||
|
||||
echo "$stdout" | jq -r '.[] | "\(.id)"'
|
||||
}
|
||||
|
||||
verify_token_exists() {
|
||||
if [ -z "$PATCHWORK_TOKEN" ]; then
|
||||
echo "For this feature you need \$PATCHWORK_TOKEN"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
set_patch_state() {
|
||||
local patch_id="$1"
|
||||
local state="$2"
|
||||
|
||||
verify_token_exists
|
||||
|
||||
curl -k -X PATCH \
|
||||
-H "Authorization: Token $PATCHWORK_TOKEN" \
|
||||
-F "state=$state" \
|
||||
"$PATCHWORK_URL/api/patches/$patch_id/"
|
||||
|
||||
[ $? -eq 0 ] || exit 1
|
||||
}
|
||||
|
||||
set_series_state() {
|
||||
if [ $# -ne 2 ]; then
|
||||
echo "'state' command expects 2 parameters ($#)"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
local series_id="$1"
|
||||
local state="$2"
|
||||
|
||||
get_patches "$series_id" | while read -r patch_id; do
|
||||
if [ "$patch_id" ]; then
|
||||
set_patch_state "$patch_id" "$state"
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
get_checks() {
|
||||
local patch_id="$1"
|
||||
local stdout
|
||||
|
||||
stdout="$(curl -k -G $PATCHWORK_URL/api/patches/$patch_id/checks/)"
|
||||
|
||||
[ $? -eq 0 ] || exit 1
|
||||
|
||||
echo "$stdout" | jq -r '.[] | "\(.id)"'
|
||||
}
|
||||
|
||||
already_tested() {
|
||||
local series_id="$1"
|
||||
|
||||
get_patches "$series_id" | while read -r patch_id; do
|
||||
[ "$patch_id" ] || continue
|
||||
|
||||
get_checks "$patch_id" | while read -r check_id; do
|
||||
if [ -n "$check_id" ]; then
|
||||
echo "$check_id"
|
||||
return
|
||||
fi
|
||||
done
|
||||
done
|
||||
}
|
||||
|
||||
verify_new_patches() {
|
||||
local tmp=$(mktemp -d)
|
||||
local output="$tmp/series_ids.txt"
|
||||
|
||||
touch "$output"
|
||||
|
||||
fetch_series | while read -r series_id series_mbox; do
|
||||
[ "$series_id" ] || continue
|
||||
|
||||
tested=$(already_tested "$series_id")
|
||||
[ "$tested" ] && continue
|
||||
|
||||
echo "$series_id|$series_mbox" >>"$output"
|
||||
done
|
||||
|
||||
cat "$output"
|
||||
}
|
||||
|
||||
send_results() {
|
||||
if [ $# -ne 4 -a $# -ne 5 ]; then
|
||||
echo "'check' command expects 4 or 5 parameters ($#)"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
local series_id="$1"
|
||||
local target_url="$2"
|
||||
|
||||
verify_token_exists
|
||||
|
||||
local context=$(echo "$3" | sed 's/:/_/g; s/\//-/g; s/\./-/g')
|
||||
|
||||
[ "$CC" ] && context="${context}_${CC}"
|
||||
[ "$ARCH" ] && context="${context}_${ARCH}"
|
||||
|
||||
local result="$4"
|
||||
[ "$result" = "cancelled" ] && return
|
||||
|
||||
local description="${5:-$result}"
|
||||
|
||||
local state="fail"
|
||||
|
||||
# patchwork REST API allowed states: pending, success, warning, fail.
|
||||
# https://github.com/getpatchwork/patchwork/blob/main/docs/api/schemas/v1.2/patchwork.yaml#L708
|
||||
# https://patchwork.readthedocs.io/en/latest/api/rest/schemas/v1.2/#get--api-1.2-patches-patch_id-checks
|
||||
case "$result" in
|
||||
success|pending) state=$result;;
|
||||
esac
|
||||
|
||||
get_patches "$series_id" | while read -r patch_id; do
|
||||
[ "$patch_id" ] || continue
|
||||
|
||||
curl -k -X POST \
|
||||
-H "Authorization: Token $PATCHWORK_TOKEN" \
|
||||
-F "state=$state" \
|
||||
-F "context=$context" \
|
||||
-F "target_url=$target_url" \
|
||||
-F "description=$description" \
|
||||
"$PATCHWORK_URL/api/patches/$patch_id/checks/"
|
||||
|
||||
[ $? -eq 0 ] || exit 1
|
||||
done
|
||||
}
|
||||
|
||||
case "$1" in
|
||||
state)
|
||||
set_series_state "$2" "$3"
|
||||
;;
|
||||
check)
|
||||
send_results "$2" "$3" "$4" "$5" "$6"
|
||||
;;
|
||||
verify)
|
||||
verify_new_patches
|
||||
;;
|
||||
*)
|
||||
echo "Available commands: state, check, verify" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
@@ -0,0 +1,15 @@
|
||||
#!/bin/sh -eux
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
# Copyright (c) 2023 SUSE LLC
|
||||
|
||||
zyp="zypper --non-interactive install --force-resolution --no-recommends"
|
||||
|
||||
$zyp \
|
||||
iproute2 \
|
||||
keyutils \
|
||||
libaio1 \
|
||||
libmnl0 \
|
||||
libnuma1 \
|
||||
libtirpc3
|
||||
|
||||
useradd ltp
|
||||
+42
-29
@@ -1,33 +1,46 @@
|
||||
#!/bin/sh
|
||||
# Copyright (c) 2018-2021 Petr Vorel <pvorel@suse.cz>
|
||||
set -ex
|
||||
#!/bin/sh -eux
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
# Copyright (c) 2018-2025 Petr Vorel <pvorel@suse.cz>
|
||||
|
||||
zyp="zypper --non-interactive install --force-resolution --no-recommends"
|
||||
|
||||
$zyp \
|
||||
asciidoc \
|
||||
autoconf \
|
||||
automake \
|
||||
clang \
|
||||
findutils \
|
||||
gcc \
|
||||
git \
|
||||
gzip \
|
||||
iproute2 \
|
||||
make \
|
||||
kernel-default-devel \
|
||||
keyutils-devel \
|
||||
libacl-devel \
|
||||
libaio-devel \
|
||||
libcap-devel \
|
||||
libmnl-devel \
|
||||
libnuma-devel \
|
||||
libopenssl-devel \
|
||||
libselinux-devel \
|
||||
libtirpc-devel \
|
||||
linux-glibc-devel \
|
||||
lsb-release \
|
||||
perl-JSON \
|
||||
pkg-config
|
||||
i=10
|
||||
while [ $i != 0 ]; do
|
||||
$zyp \
|
||||
autoconf \
|
||||
automake \
|
||||
clang \
|
||||
curl \
|
||||
jq \
|
||||
findutils \
|
||||
gcc \
|
||||
git \
|
||||
gzip \
|
||||
iproute2 \
|
||||
make \
|
||||
kernel-default-devel \
|
||||
keyutils-devel \
|
||||
libacl-devel \
|
||||
libaio-devel \
|
||||
libcap-devel \
|
||||
libmnl-devel \
|
||||
libnuma-devel \
|
||||
libopenssl-devel \
|
||||
libselinux-devel \
|
||||
libtirpc-devel \
|
||||
linux-glibc-devel \
|
||||
lsb-release \
|
||||
pkg-config
|
||||
|
||||
$zyp ruby2.7-rubygem-asciidoctor || $zyp ruby2.5-rubygem-asciidoctor || true
|
||||
ret=$?
|
||||
|
||||
if [ $ret -eq 106 ]; then
|
||||
echo "Broken repositories, try $i..."
|
||||
sleep 5
|
||||
i=$((i-1))
|
||||
continue
|
||||
fi
|
||||
break
|
||||
done
|
||||
|
||||
exit $ret
|
||||
|
||||
+66
-1
@@ -1 +1,66 @@
|
||||
debian.sh
|
||||
#!/bin/sh -eux
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
# Copyright (c) 2018-2024 Petr Vorel <pvorel@suse.cz>
|
||||
|
||||
# workaround for missing oldstable-updates repository
|
||||
# W: Failed to fetch http://deb.debian.org/debian/dists/oldstable-updates/main/binary-amd64/Packages
|
||||
grep -v oldstable-updates /etc/apt/sources.list > /tmp/sources.list && mv /tmp/sources.list /etc/apt/sources.list
|
||||
|
||||
apt update
|
||||
|
||||
# workaround for Ubuntu impish asking to interactively configure tzdata
|
||||
export DEBIAN_FRONTEND="noninteractive"
|
||||
|
||||
install="apt install -y --no-install-recommends"
|
||||
remove="apt remove -y"
|
||||
|
||||
# libc6-dev and libtirpc-dev are hard dependencies for gcc toolchain
|
||||
# LTP should be compilable without linux-libc-dev, but we expect kernel headers.
|
||||
pkg_minimal="
|
||||
autoconf
|
||||
automake
|
||||
build-essential
|
||||
debhelper
|
||||
devscripts
|
||||
clang
|
||||
curl
|
||||
jq
|
||||
gcc
|
||||
git
|
||||
iproute2
|
||||
libc6-dev
|
||||
libtirpc-dev
|
||||
linux-libc-dev
|
||||
lsb-release
|
||||
pkg-config
|
||||
"
|
||||
|
||||
pkg_nonessential="
|
||||
acl-dev
|
||||
libacl1-dev
|
||||
libaio-dev
|
||||
libcap-dev
|
||||
libkeyutils-dev
|
||||
libnuma-dev
|
||||
libmnl-dev
|
||||
libselinux1-dev
|
||||
libsepol-dev
|
||||
libssl-dev
|
||||
"
|
||||
|
||||
case "$ACTION" in
|
||||
minimal)
|
||||
echo "=== Installing only minimal dependencies ==="
|
||||
$install $pkg_minimal
|
||||
;;
|
||||
remove-nonessential)
|
||||
echo "=== Make sure devel libraries are removed ==="
|
||||
$remove $pkg_nonessential
|
||||
;;
|
||||
*)
|
||||
echo "=== Installing dependencies ==="
|
||||
$install $pkg_minimal $pkg_nonessential
|
||||
;;
|
||||
esac
|
||||
|
||||
df -hT
|
||||
|
||||
+66
-51
@@ -1,9 +1,14 @@
|
||||
# Copyright (c) Linux Test Project, 2008-2025
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
AC_PREREQ(2.64)
|
||||
AC_INIT([ltp], [LTP_VERSION], [ltp@lists.linux.it])
|
||||
AC_CONFIG_AUX_DIR([.])
|
||||
AM_INIT_AUTOMAKE
|
||||
AC_CONFIG_HEADERS([include/config.h])
|
||||
AC_CONFIG_MACRO_DIR([m4])
|
||||
|
||||
# Adding files here? Please update include/mk/automake.mk
|
||||
AC_CONFIG_FILES([ \
|
||||
include/mk/config.mk \
|
||||
include/mk/config-openposix.mk \
|
||||
@@ -27,6 +32,7 @@ AC_PROG_RANLIB
|
||||
AC_DEFUN([AC_PROG_STRIP], [AC_CHECK_TOOL(STRIP, strip, :)])
|
||||
AC_PROG_STRIP
|
||||
AC_PROG_YACC
|
||||
AC_CHECK_TOOL([OBJCOPY], [objcopy], [:])
|
||||
|
||||
m4_ifndef([PKG_CHECK_EXISTS],
|
||||
[m4_fatal([must install pkg-config or pkgconfig and pkg.m4 macro (usual dependency), see INSTALL])])
|
||||
@@ -34,16 +40,22 @@ m4_ifndef([PKG_CHECK_EXISTS],
|
||||
AC_PREFIX_DEFAULT(/opt/ltp)
|
||||
|
||||
AC_CHECK_DECLS([IFLA_NET_NS_PID],,,[#include <linux/if_link.h>])
|
||||
AC_CHECK_DECLS([LANDLOCK_RULE_PATH_BENEATH],,,[#include <linux/landlock.h>])
|
||||
AC_CHECK_DECLS([LANDLOCK_RULE_NET_PORT],,,[#include <linux/landlock.h>])
|
||||
AC_CHECK_DECLS([MADV_MERGEABLE],,,[#include <sys/mman.h>])
|
||||
AC_CHECK_DECLS([NFTA_CHAIN_ID, NFTA_VERDICT_CHAIN_ID],,,[#include <linux/netfilter/nf_tables.h>])
|
||||
AC_CHECK_DECLS([PR_CAPBSET_DROP, PR_CAPBSET_READ],,,[#include <sys/prctl.h>])
|
||||
AC_CHECK_DECLS([SEM_STAT_ANY],,,[#include <sys/sem.h>])
|
||||
|
||||
AC_CHECK_HEADERS_ONCE([ \
|
||||
aio.h \
|
||||
asm/ldt.h \
|
||||
asm/prctl.h \
|
||||
cpuid.h \
|
||||
emmintrin.h \
|
||||
ifaddrs.h \
|
||||
keyutils.h \
|
||||
linux/blkdev.h \
|
||||
linux/can.h \
|
||||
linux/cgroupstats.h \
|
||||
linux/cryptouser.h \
|
||||
@@ -52,18 +64,22 @@ AC_CHECK_HEADERS_ONCE([ \
|
||||
linux/fs.h \
|
||||
linux/futex.h \
|
||||
linux/genetlink.h \
|
||||
linux/genhd.h \
|
||||
linux/if_alg.h \
|
||||
linux/if_ether.h \
|
||||
linux/if_packet.h \
|
||||
linux/io_uring.h \
|
||||
linux/ioprio.h \
|
||||
linux/keyctl.h \
|
||||
linux/landlock.h \
|
||||
linux/lsm.h \
|
||||
linux/mempolicy.h \
|
||||
linux/module.h \
|
||||
linux/mount.h \
|
||||
linux/netlink.h \
|
||||
linux/seccomp.h \
|
||||
linux/securebits.h \
|
||||
linux/tls.h \
|
||||
linux/tty.h \
|
||||
linux/types.h \
|
||||
linux/userfaultfd.h \
|
||||
@@ -74,6 +90,7 @@ AC_CHECK_HEADERS_ONCE([ \
|
||||
sys/inotify.h \
|
||||
sys/pidfd.h
|
||||
sys/prctl.h \
|
||||
sys/random.h \
|
||||
sys/shm.h \
|
||||
sys/timerfd.h \
|
||||
sys/ustat.h \
|
||||
@@ -86,6 +103,7 @@ AC_SUBST(HAVE_FTS_H, $have_fts)
|
||||
AC_CHECK_HEADERS(linux/vm_sockets.h, [], [], [#include <sys/socket.h>])
|
||||
|
||||
AC_CHECK_FUNCS_ONCE([ \
|
||||
cachestat \
|
||||
clone3 \
|
||||
close_range \
|
||||
copy_file_range \
|
||||
@@ -94,7 +112,8 @@ AC_CHECK_FUNCS_ONCE([ \
|
||||
execveat \
|
||||
faccessat2 \
|
||||
fallocate \
|
||||
fchownat \
|
||||
file_getattr \
|
||||
file_setattr \
|
||||
fsconfig \
|
||||
fsmount \
|
||||
fsopen \
|
||||
@@ -113,8 +132,6 @@ AC_CHECK_FUNCS_ONCE([ \
|
||||
mallinfo \
|
||||
mallinfo2 \
|
||||
mallopt \
|
||||
mkdirat \
|
||||
mknodat \
|
||||
modify_ldt \
|
||||
mount_setattr \
|
||||
move_mount \
|
||||
@@ -133,9 +150,7 @@ AC_CHECK_FUNCS_ONCE([ \
|
||||
pwritev2 \
|
||||
quotactl_fd \
|
||||
rand_r \
|
||||
readlinkat \
|
||||
recvmmsg \
|
||||
renameat \
|
||||
renameat2 \
|
||||
sched_getcpu \
|
||||
sendmmsg \
|
||||
@@ -174,20 +189,29 @@ AC_CHECK_TYPES([enum kcmp_type],,,[#include <linux/kcmp.h>])
|
||||
AC_CHECK_TYPES([struct acct_v3],,,[#include <sys/acct.h>])
|
||||
AC_CHECK_TYPES([struct af_alg_iv, struct sockaddr_alg],,,[# include <linux/if_alg.h>])
|
||||
AC_CHECK_TYPES([struct fanotify_event_info_fid, struct fanotify_event_info_error,
|
||||
struct fanotify_event_info_header, struct fanotify_event_info_pidfd],,,[#include <sys/fanotify.h>])
|
||||
struct fanotify_event_info_header, struct fanotify_event_info_pidfd,
|
||||
struct fanotify_event_info_range],,,[#include <sys/fanotify.h>])
|
||||
AC_CHECK_TYPES([struct file_clone_range],,,[#include <linux/fs.h>])
|
||||
AC_CHECK_TYPES([struct file_dedupe_range],,,[#include <linux/fs.h>])
|
||||
AC_CHECK_TYPES([struct procmap_query],,,[#include <linux/fs.h>])
|
||||
|
||||
AC_CHECK_TYPES([struct file_handle],,,[
|
||||
#define _GNU_SOURCE
|
||||
#include <fcntl.h>
|
||||
])
|
||||
|
||||
AC_CHECK_TYPES([struct fs_quota_statv],,,[#include <xfs/xqm.h>])
|
||||
AC_CHECK_TYPES([struct fs_quota_statv],,,[
|
||||
#define _GNU_SOURCE
|
||||
#include <xfs/xqm.h>
|
||||
])
|
||||
|
||||
AC_CHECK_TYPES([struct if_nextdqblk],,,[#include <linux/quota.h>])
|
||||
AC_CHECK_TYPES([struct iovec],,,[#include <sys/uio.h>])
|
||||
AC_CHECK_TYPES([struct ipc64_perm],,,[#include <sys/ipcbuf.h>])
|
||||
AC_CHECK_TYPES([struct loop_config],,,[#include <linux/loop.h>])
|
||||
|
||||
AC_CHECK_TYPES([struct landlock_path_beneath_attr],,,[#include <linux/landlock.h>])
|
||||
AC_CHECK_TYPES([struct landlock_net_port_attr],,,[#include <linux/landlock.h>])
|
||||
AC_CHECK_TYPES([struct lsm_ctx],,,[#include <linux/lsm.h>])
|
||||
AC_CHECK_TYPES([struct mmsghdr],,,[
|
||||
#define _GNU_SOURCE
|
||||
#include <sys/types.h>
|
||||
@@ -222,7 +246,8 @@ AC_CHECK_TYPES([struct xt_entry_match, struct xt_entry_target],,,[
|
||||
])
|
||||
|
||||
AC_CHECK_TYPES([struct __kernel_old_timeval, struct __kernel_old_timespec, struct __kernel_timespec,
|
||||
struct __kernel_old_itimerspec, struct __kernel_itimerspec],,,[#include <sys/socket.h>])
|
||||
struct __kernel_old_itimerspec, struct __kernel_itimerspec,
|
||||
struct __kernel_old_itimerval],,,[#include <sys/socket.h>])
|
||||
|
||||
AC_CHECK_TYPES([struct futex_waitv],,,[#include <linux/futex.h>])
|
||||
AC_CHECK_TYPES([struct mount_attr],,,[
|
||||
@@ -233,6 +258,25 @@ AC_CHECK_TYPES([struct mount_attr],,,[
|
||||
#endif
|
||||
])
|
||||
|
||||
AC_CHECK_TYPES([struct cachestat_range],,,[#include <sys/mman.h>])
|
||||
AC_CHECK_TYPES([struct cachestat],,,[#include <sys/mman.h>])
|
||||
|
||||
# Defined in <linux/mount.h>, but include/lapi/mount.h includes <sys/mount.h> */
|
||||
AC_CHECK_TYPES([struct mnt_id_req],,,[#include <sys/mount.h>])
|
||||
AC_CHECK_TYPES([struct statmount],,,[#include <sys/mount.h>])
|
||||
AC_CHECK_MEMBERS([struct statmount.mnt_ns_id],,,[#include <unistd.h>
|
||||
#include <linux/mount.h>])
|
||||
|
||||
AC_CHECK_TYPES([struct pidfd_info],,,[#include <sys/pidfd.h>])
|
||||
AC_CHECK_TYPES([struct file_attr],,,[#include <linux/fs.h>])
|
||||
|
||||
AC_CHECK_TYPES([struct fsxattr],,,[#include <linux/fs.h>])
|
||||
|
||||
AC_CHECK_TYPES([struct sockaddr_vm],,,[
|
||||
#include <sys/socket.h>
|
||||
#include <linux/vm_sockets.h>
|
||||
])
|
||||
|
||||
# Tools knobs
|
||||
|
||||
# Bash
|
||||
@@ -248,33 +292,6 @@ else
|
||||
AC_SUBST([WITH_BASH],["no"])
|
||||
fi
|
||||
|
||||
# metadata
|
||||
AC_ARG_ENABLE([metadata],
|
||||
[AS_HELP_STRING([--disable-metadata],
|
||||
[Disable metadata generation (both HTML and PDF, default no)])],
|
||||
[], [enable_metadata=yes]
|
||||
)
|
||||
AC_ARG_ENABLE([metadata_html],
|
||||
[AS_HELP_STRING([--disable-metadata-html],
|
||||
[Disable metadata HTML generation (default no)])],
|
||||
[], [enable_metadata_html=yes]
|
||||
)
|
||||
|
||||
AC_ARG_ENABLE([metadata_pdf],
|
||||
[AS_HELP_STRING([--enable-metadata-pdf],
|
||||
[Enable metadata PDF generation (default no)])],
|
||||
[], [enable_metadata_pdf=no]
|
||||
)
|
||||
|
||||
AC_ARG_WITH([metadata_generator],
|
||||
[AS_HELP_STRING([--with-metadata-generator=asciidoc|asciidoctor],
|
||||
[Specify metadata generator to use (default autodetect)])],
|
||||
[with_metadata_generator=$withval],
|
||||
[with_metadata_generator=detect]
|
||||
)
|
||||
|
||||
LTP_DOCPARSE
|
||||
|
||||
# Expect
|
||||
AC_ARG_WITH([expect],
|
||||
[AS_HELP_STRING([--with-expect],
|
||||
@@ -359,20 +376,18 @@ fi
|
||||
# TODO: testcases/realtime requires bash and python.
|
||||
AC_ARG_WITH([realtime-testsuite],
|
||||
[AS_HELP_STRING([--with-realtime-testsuite],
|
||||
[compile and install the realtime testsuite])],
|
||||
[unused, kept for compatibility reason])],
|
||||
[with_realtime_testsuite=$withval],
|
||||
[with_realtime_testsuite=no]
|
||||
)
|
||||
|
||||
if test "x$with_realtime_testsuite" = xyes; then
|
||||
AC_SUBST([WITH_REALTIME_TESTSUITE],["yes"])
|
||||
# Run configure on testcases/realtime as well.
|
||||
AC_CONFIG_SUBDIRS([testcases/realtime])
|
||||
else
|
||||
AC_SUBST([WITH_REALTIME_TESTSUITE],["no"])
|
||||
fi
|
||||
|
||||
AC_CONFIG_COMMANDS([syscalls.h], [cd ${ac_top_srcdir}/include/lapi/syscalls; ./regen.sh])
|
||||
AC_CONFIG_COMMANDS([syscalls.h], [cd ${ac_top_srcdir}/include/lapi/syscalls; ./generate_syscalls.sh ../syscalls.h; cd - >/dev/null])
|
||||
|
||||
# custom functions
|
||||
# NOTE: don't create custom functions for simple checks, put them into this file
|
||||
@@ -386,17 +401,15 @@ LTP_CHECK_FORTIFY_SOURCE
|
||||
LTP_CHECK_KERNEL_DEVEL
|
||||
LTP_CHECK_KEYUTILS_SUPPORT
|
||||
LTP_CHECK_LIBMNL
|
||||
LTP_CHECK_LINUX_PTRACE
|
||||
LTP_CHECK_LINUXRANDOM
|
||||
LTP_CHECK_NOMMU_LINUX
|
||||
LTP_CHECK_SELINUX
|
||||
LTP_CHECK_SYNC_ADD_AND_FETCH
|
||||
LTP_CHECK_SYSCALL_EVENTFD
|
||||
LTP_CHECK_SYSCALL_FCNTL
|
||||
LTP_CHECK_FSVERITY
|
||||
|
||||
AX_CHECK_COMPILE_FLAG([-no-pie], [LTP_CFLAGS_NOPIE=1])
|
||||
AX_CHECK_COMPILE_FLAG([-ffixed-ebp], [LTP_CFLAGS_FFIXED_EBP=1])
|
||||
AC_SUBST([LTP_CFLAGS_NOPIE])
|
||||
AC_SUBST([LTP_CFLAGS_FFIXED_EBP])
|
||||
|
||||
if test "x$with_numa" = xyes; then
|
||||
LTP_CHECK_SYSCALL_NUMA
|
||||
@@ -407,7 +420,6 @@ fi
|
||||
AC_DEFINE_UNQUOTED(NUMA_ERROR_MSG, ["$numa_error_msg"], [Error message when no NUMA support])
|
||||
|
||||
|
||||
LTP_CHECK_SYSCALL_SIGNALFD
|
||||
LTP_CHECK_SYSCALL_UTIMENSAT
|
||||
LTP_CHECK_TASKSTATS
|
||||
test "x$with_tirpc" = xyes && LTP_CHECK_TIRPC
|
||||
@@ -422,10 +434,12 @@ AC_LINK_IFELSE([AC_LANG_PROGRAM()],
|
||||
[
|
||||
AC_MSG_RESULT([yes])
|
||||
AC_SUBST([WITH_KVM_TESTSUITE],["yes"])
|
||||
have_kvm=yes
|
||||
],
|
||||
[
|
||||
AC_MSG_RESULT([no])
|
||||
AC_SUBST([WITH_KVM_TESTSUITE],["no"])
|
||||
have_kvm=no
|
||||
])
|
||||
_AC_LANG_PREFIX[]FLAGS="$ltp_backup_flags"
|
||||
LDFLAGS="$ltp_backup_ldflags"
|
||||
@@ -435,8 +449,10 @@ AC_OUTPUT
|
||||
cat << EOF
|
||||
|
||||
TESTSUITES
|
||||
kernel modules: $WITH_MODULES (kernel: $LINUX_VERSION)
|
||||
KVM testsuite: $have_kvm
|
||||
open posix testsuite: ${with_open_posix_testsuite:-no}
|
||||
realtime testsuite: ${with_realtime_testsuite:-no}
|
||||
TI-RPC testsuite: ${with_tirpc:-yes}
|
||||
|
||||
LIBRARIES
|
||||
keyutils: ${have_keyutils:-yes}
|
||||
@@ -448,9 +464,8 @@ libmnl: ${have_libmnl:-yes}
|
||||
libnuma: ${have_libnuma:-no} (headers: ${have_numa_headers:-yes}, v2 headers: ${have_numa_headers_v2:-no})
|
||||
libtirpc: ${have_libtirpc:-no}
|
||||
glibc SUN-RPC: ${have_rpc_glibc:-no}
|
||||
|
||||
METADATA
|
||||
metadata generator: $with_metadata_generator
|
||||
HTML metadata: $with_metadata_html
|
||||
PDF metadata: $with_metadata_pdf
|
||||
EOF
|
||||
|
||||
if test "x$with_realtime_testsuite" = xyes; then
|
||||
AC_MSG_WARN([--with-realtime-testsuite has no effect and is kept for compatibilty reason. It will be removed in the future.])
|
||||
fi
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
.venv/
|
||||
html/
|
||||
build/
|
||||
_static/syscalls.rst
|
||||
_static/tests.rst
|
||||
syscalls.tbl
|
||||
@@ -1,218 +0,0 @@
|
||||
Short introduction into LTP build system
|
||||
========================================
|
||||
|
||||
******************************************************************************
|
||||
The following document briefly describes the steps and methodologies used for
|
||||
the new and improved Makefile system.
|
||||
|
||||
Changelog:
|
||||
|
||||
* Initial version: Ngie Cooper <yaneurabeya@gmail.com>
|
||||
* Reformated for asciidoc: Cyril Hrubis <chrubis@suse.cz>
|
||||
******************************************************************************
|
||||
|
||||
The Problem
|
||||
-----------
|
||||
|
||||
The problem with the old Makefile system is that it was very difficult to
|
||||
maintain and it lacked any sense of formal structure, thus developing for LTP
|
||||
and including new targets was more difficult than it should have been
|
||||
(maintenance). Furthermore, proper option-based cross-compilation was
|
||||
impossible due to the fact that the Makefiles didn't support a prefixing
|
||||
system, and the appropriate implicit / static rules hadn't been configured to
|
||||
compile into multiple object directories for out-of-tree build support (ease of
|
||||
use / functionality). Finally, there wasn't a means to setup dependencies
|
||||
between components, such that if a component required libltp.a in order to
|
||||
compile, it would go off and compile libltp.a first (ease of use).
|
||||
|
||||
These items needed to be fixed to reduce maintenance nightmares for the
|
||||
development community contributing to LTP, and the project maintainers.
|
||||
|
||||
Design
|
||||
------
|
||||
|
||||
The system was designed such that including a single GNU Makefile compatible
|
||||
set in each new directory component is all that's essentially required to
|
||||
build the system.
|
||||
|
||||
Say you had a directory like the following (with .c files in them which
|
||||
directly tie into applications, e.g. baz.c -> baz):
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
.../foo/
|
||||
|--> Makefile
|
||||
|
|
||||
--> bar/
|
||||
|
|
||||
--> Makefile
|
||||
|
|
||||
--> baz.c
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Here's an example of how one would accomplish that:
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
.../foo/Makefile:
|
||||
#
|
||||
# Copyright disclaimer goes here -- please use GPLv2.
|
||||
#
|
||||
|
||||
top_srcdir ?= ..
|
||||
|
||||
include $(top_srcdir)/include/mk/env_pre.mk
|
||||
include $(top_srcdir)/include/mk/generic_trunk_target.mk
|
||||
|
||||
.../foo/bar/Makefile:
|
||||
#
|
||||
# Copyright disclaimer goes here -- please use GPLv2.
|
||||
#
|
||||
|
||||
top_srcdir ?= ..
|
||||
|
||||
include $(top_srcdir)/include/mk/env_pre.mk
|
||||
include $(top_srcdir)/include/mk/generic_leaf_target.mk
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Kernel Modules
|
||||
--------------
|
||||
|
||||
Some of the tests need to build kernel modules, happily LTP has
|
||||
infrastructure for this.
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
ifneq ($(KERNELRELEASE),)
|
||||
|
||||
obj-m := module01.o
|
||||
|
||||
else
|
||||
|
||||
top_srcdir ?= ../../../..
|
||||
include $(top_srcdir)/include/mk/testcases.mk
|
||||
|
||||
REQ_VERSION_MAJOR := 2
|
||||
REQ_VERSION_PATCH := 6
|
||||
MAKE_TARGETS := test01 test02 module01.ko
|
||||
|
||||
include $(top_srcdir)/include/mk/module.mk
|
||||
include $(top_srcdir)/include/mk/generic_leaf_target.mk
|
||||
|
||||
endif
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
This is example Makefile that allows you build kernel modules inside of LTP.
|
||||
The prerequisites for the build are detected by the 'configure' script.
|
||||
|
||||
The 'REQ_VERSION_MAJOR' and 'REQ_VERSION_PATCH' describe minimal kernel
|
||||
version for which the build system tries to build the module.
|
||||
|
||||
The buildsystem is also forward compatible with changes in Linux kernel
|
||||
internal API so that if module fails to build the failure is ignored both on
|
||||
build and installation. If the userspace counterpart of the test fails to load
|
||||
the module because the file does not exists, the test is skipped.
|
||||
|
||||
Note the 'ifneq($(KERNELRELEASE),)', the reason it's there is that the
|
||||
Makefile is executed twice, once by LTP build system and once by kernel
|
||||
kbuild, see 'Documentation/kbuild/modules.txt' in the Linux kernel tree for
|
||||
details on external module build.
|
||||
|
||||
Make Rules and Make Variables
|
||||
-----------------------------
|
||||
|
||||
When using make rules, avoid writing ad hoc rules like:
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
[prog]: [dependencies]
|
||||
cc -I../../include $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) $(LDLIBS) \
|
||||
-o [prog] [dependencies]
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
etc. This makes cross-compilation and determinism difficult, if not impossible.
|
||||
Besides, implicit rules are your friends and as long as you use `MAKEOPTS=;' in
|
||||
the top-level caller (or do $(subst r,$(MAKEOPTS)) to remove -r), the compile
|
||||
will complete successfully, assuming all other prerequisites have been
|
||||
fulfilled (libraries, headers, etc).
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
$(AR) : The library archiver.
|
||||
|
||||
$(CC) : The system C compiler.
|
||||
|
||||
$(CPP) : The system C preprocessor.
|
||||
|
||||
$(CFLAGS) : C compiler flags.
|
||||
|
||||
$(CPPFLAGS) : Preprocessor flags, e.g. -I arguments.
|
||||
|
||||
$(DEBUG_CFLAGS) : Debug flags to pass to $(CC), -g, etc.
|
||||
|
||||
$(KVM_LD) : Special linker for wrapping KVM payload binaries
|
||||
into linkable object files. Defaults to $(LD).
|
||||
Change this variable if the KVM Makefile fails
|
||||
to build files named *-payload.o.
|
||||
|
||||
$(LD) : The system linker (typically $(CC), but not
|
||||
necessarily).
|
||||
|
||||
$(LDFLAGS) : What to pass in to the linker, including -L arguments
|
||||
and other ld arguments, apart from -l library
|
||||
includes (see $(LDLIBS)).
|
||||
|
||||
This should be done in the $(CC) args passing style
|
||||
when LD := $(CC), e.g. `-Wl,-foo', as opposed to
|
||||
`-foo'.
|
||||
|
||||
$(LDLIBS) : Libraries to pass to the linker (e.g. -lltp, etc).
|
||||
|
||||
$(LTPLDLIBS) : LTP internal libraries i.e. these in libs/ directory.
|
||||
|
||||
$(OPT_CFLAGS) : Optimization flags to pass into the C compiler, -O2,
|
||||
etc. If you specify -O2 or higher, you should also
|
||||
specify -fno-strict-aliasing, because of gcc
|
||||
fstrict-aliasing optimization bugs in the tree
|
||||
optimizer. Search for `fstrict-aliasing optimization
|
||||
bug' with your favorite search engine.
|
||||
|
||||
Examples of more recent bugs:
|
||||
1. tree-optimization/17510
|
||||
2. tree-optimization/39100
|
||||
|
||||
Various bugs have occurred in the past due to buggy
|
||||
logic in the tree-optimization portion of the gcc
|
||||
compiler, from 3.3.x to 4.4.
|
||||
|
||||
$(RANLIB) : What to run after archiving a library.
|
||||
|
||||
$(WCFLAGS) : Warning flags to pass to $(CC), e.g. -Werror,
|
||||
-Wall, etc.
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Make System Variables
|
||||
---------------------
|
||||
|
||||
A series of variables are used within the make system that direct what actions
|
||||
need to be taken. Rather than me listing the variables here, please with their
|
||||
intended uses, please refer to the comments contained in
|
||||
+.../include/mk/env_pre.mk+.
|
||||
|
||||
Guidelines and Recommendations
|
||||
------------------------------
|
||||
|
||||
Of course, the GNU Make manual is key to understanding the Make system, but
|
||||
here are the following sections and chapters I suggest reviewing:
|
||||
|
||||
link:http://www.gnu.org/software/make/manual/make.html#Implicit-Rules[Implicit Rules]
|
||||
link:http://www.gnu.org/software/make/manual/make.html#Using-Variables[Variables and Expansion]
|
||||
link:http://www.gnu.org/software/make/manual/make.html#Origin-Function[Origin Use]
|
||||
link:http://www.gnu.org/software/make/manual/make.html#Directory-Search[VPath Use]
|
||||
|
||||
Before Committing
|
||||
-----------------
|
||||
|
||||
One should rebuild from scratch before committing. Please see INSTALL for more
|
||||
details.
|
||||
|
||||
Other Errata
|
||||
------------
|
||||
|
||||
Please see TODO for any issues related to the Makefile infrastructure, and
|
||||
build structure / source tree in general.
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,487 +0,0 @@
|
||||
LTP KVM Test API
|
||||
================
|
||||
|
||||
Testing KVM is more complex than other Linux features. Some KVM bugs allow
|
||||
userspace code running inside the virtual machine to bypass (emulated) hardware
|
||||
access restrictions and elevate its privileges inside the guest operating
|
||||
system. The worst types of KVM bugs may even allow the guest code to crash or
|
||||
compromise the physical host. KVM tests therefore need to be split into two
|
||||
components – a KVM controller program running on the physical host and a guest
|
||||
payload program running inside the VM. The cooperation of these two components
|
||||
allows testing even of bugs that somehow cross the virtualization boundary.
|
||||
|
||||
NOTE: See also
|
||||
https://github.com/linux-test-project/ltp/wiki/Test-Writing-Guidelines[Test Writing Guidelines],
|
||||
https://github.com/linux-test-project/ltp/wiki/C-Test-Case-Tutorial[C Test Case Tutorial],
|
||||
https://github.com/linux-test-project/ltp/wiki/C-Test-API[C Test API].
|
||||
|
||||
1. Basic KVM test structure
|
||||
---------------------------
|
||||
|
||||
KVM tests are simple C source files containing both the KVM controller code
|
||||
and the guest payload code separated by `#ifdef COMPILE_PAYLOAD` preprocessor
|
||||
condition. The file will be compiled twice. Once to compile the payload part,
|
||||
once to compile the KVM controller part and embed the payload binary inside.
|
||||
The result is a single self-contained binary that'll execute the embedded
|
||||
payload inside a KVM virtual machine and print results in the same format as
|
||||
a normal LTP test.
|
||||
|
||||
A KVM test source should start with `#include "kvm_test.h"` instead of the
|
||||
usual `tst_test.h`. The `kvm_test.h` header file will include the other basic
|
||||
headers appropriate for the current compilation pass. Everything else in the
|
||||
source file should be enclosed in `#ifdef COMPILE_PAYLOAD ... #else ... #endif`
|
||||
condition, including any other header file includes. Note that the standard
|
||||
LTP headers are not available in the payload compilation pass, only the KVM
|
||||
guest library headers can be included.
|
||||
|
||||
.Example KVM test
|
||||
[source,c]
|
||||
-------------------------------------------------------------------------------
|
||||
#include "kvm_test.h"
|
||||
|
||||
#ifdef COMPILE_PAYLOAD
|
||||
|
||||
/* Guest payload code */
|
||||
|
||||
void main(void)
|
||||
{
|
||||
tst_res(TPASS, "Hello, world!");
|
||||
}
|
||||
|
||||
#else /* COMPILE_PAYLOAD */
|
||||
|
||||
/* KVM controller code */
|
||||
|
||||
static struct tst_test test = {
|
||||
.test_all = tst_kvm_run,
|
||||
.setup = tst_kvm_setup,
|
||||
.cleanup = tst_kvm_cleanup,
|
||||
};
|
||||
|
||||
#endif /* COMPILE_PAYLOAD */
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
The KVM controller code is a normal LTP test and needs to define an instance
|
||||
of `struct tst_test` with metadata and the usual setup, cleanup, and test
|
||||
functions. Basic implementation of all three functions is provided by the KVM
|
||||
host library.
|
||||
|
||||
On the other hand, the payload is essentially a tiny kernel that'll run
|
||||
on bare virtual hardware. It cannot access any files, Linux syscalls, standard
|
||||
library functions, etc. except for the small subset provided by the KVM guest
|
||||
library. The payload code must define a `void main(void)` function which will
|
||||
be the VM entry point of the test.
|
||||
|
||||
2. KVM host library
|
||||
-------------------
|
||||
|
||||
The KVM host library provides helper functions for creating and running
|
||||
a minimal KVM virtual machine.
|
||||
|
||||
2.1 Data structures
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
[source,c]
|
||||
-------------------------------------------------------------------------------
|
||||
struct tst_kvm_instance {
|
||||
int vm_fd, vcpu_fd;
|
||||
struct kvm_run *vcpu_info;
|
||||
size_t vcpu_info_size;
|
||||
struct kvm_userspace_memory_region ram[MAX_KVM_MEMSLOTS];
|
||||
struct tst_kvm_result *result;
|
||||
};
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
`struct tst_kvm_instance` holds the file descriptors and memory buffers
|
||||
of a single KVM virtual machine:
|
||||
|
||||
- `int vm_fd` is the main VM file descriptor created by `ioctl(KVM_CREATE_VM)`
|
||||
- `int vcpu_fd` is the virtual CPU filedescriptor created by
|
||||
`ioctl(KVM_CREATE_VCPU)`
|
||||
- `struct kvm_run *vcpu_info` is the VCPU state structure created by
|
||||
`mmap(vcpu_fd)`
|
||||
- `size_t vcpu_info_size` is the size of `vcpu_info` buffer
|
||||
- `struct kvm_userspace_memory_region ram[MAX_KVM_MEMSLOTS]` is the list
|
||||
of memory slots defined in this VM. Unused memory slots have zero
|
||||
in the `userspace_addr` field.
|
||||
- `struct tst_kvm_result *result` is a buffer for passing test result data
|
||||
from the VM to the controller program, mainly `tst_res()`/`tst_brk()` flags
|
||||
and messages.
|
||||
|
||||
[source,c]
|
||||
-------------------------------------------------------------------------------
|
||||
struct tst_kvm_result {
|
||||
int32_t result;
|
||||
int32_t lineno;
|
||||
uint64_t file_addr;
|
||||
char message[0];
|
||||
};
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
`struct tst_kvm_result` is used to pass test results and synchronization data
|
||||
between the KVM guest and the controller program. Most often, it is used
|
||||
to pass `tst_res()` and `tst_brk()` messages from the VM, but special values
|
||||
can also be used to send control flow requests both ways.
|
||||
|
||||
- `int32_t result` is the message type, either one of the `TPASS`, `TFAIL`,
|
||||
`TWARN`, `TBROK`, `TINFO` flags or a special control flow value. Errno flags
|
||||
are not supported.
|
||||
- `int32_t lineno` is the line number for `tst_res()`/`tst_brk()` messages.
|
||||
- `uint64_t file_addr` is the VM address of the filename string for
|
||||
`tst_res()`/`tst_brk()` messages.
|
||||
- `char message[0]` is the buffer for arbitrary message data, most often used
|
||||
to pass `tst_res()`/`tst_brk()` message strings.
|
||||
|
||||
2.2 Working with virtual machines
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The KVM host library provides default implementation of the setup, cleanup
|
||||
and test functions for `struct tst_test` in cases where you do not need
|
||||
to customize the VM configuration. You can either assign these functions
|
||||
to the `struct tst_test` instance directly or call them from your own function
|
||||
that does some additional steps. All three function must be used together.
|
||||
|
||||
- `void tst_kvm_setup(void)`
|
||||
- `void tst_kvm_run(void)`
|
||||
- `void tst_kvm_cleanup(void)`
|
||||
|
||||
Note: `tst_kvm_run()` calls `tst_free_all()`. Calling it will free all
|
||||
previously allocated guarded buffers.
|
||||
|
||||
- `void tst_kvm_validate_result(int value)` – Validate whether the value
|
||||
returned in `struct tst_kvm_result.result` can be safely passed
|
||||
to `tst_res()` or `tst_brk()`. If the value is not valid, the controller
|
||||
program will be terminated with error.
|
||||
|
||||
- `uint64_t tst_kvm_get_phys_address(const struct tst_kvm_instance *inst,
|
||||
uint64_t addr)` – Converts pointer value (virtual address) from KVM virtual
|
||||
machine `inst` to the corresponding physical address. Returns 0 if
|
||||
the virtual address is not mapped to any physical address. If virtual memory
|
||||
mapping is not enabled in the VM or not available on the arch at all, this
|
||||
function simply returns `addr` as is.
|
||||
|
||||
- `int tst_kvm_find_phys_memslot(const struct tst_kvm_instance *inst,
|
||||
uint64_t paddr)` – Returns index of the memory slot in KVM virtual machine
|
||||
`inst` which contains the physical address `paddr`. If the address is not
|
||||
backed by a memory buffer, returns -1.
|
||||
|
||||
- `int tst_kvm_find_memslot(const struct tst_kvm_instance *inst,
|
||||
uint64_t addr)` – Returns index of the memory slot in KVM virtual machine
|
||||
`inst` which contains the virtual address `addr`. If the virtual address
|
||||
is not mapped to a valid physical address backed by a memory buffer,
|
||||
returns -1.
|
||||
|
||||
- `void *tst_kvm_get_memptr(const struct tst_kvm_instance *inst,
|
||||
uint64_t addr)` – Converts pointer value (virtual address) from KVM virtual
|
||||
machine `inst` to host-side pointer.
|
||||
|
||||
- `void *tst_kvm_alloc_memory(struct tst_kvm_instance *inst, unsigned int slot,
|
||||
uint64_t baseaddr, size_t size, unsigned int flags)` – Allocates a guarded
|
||||
buffer of given `size` in bytes and installs it into specified memory `slot`
|
||||
of the KVM virtual machine `inst` at base address `baseaddr`. The buffer
|
||||
will be automatically page aligned at both ends. See the kernel
|
||||
documentation of `KVM_SET_USER_MEMORY_REGION` ioctl for list of valid
|
||||
`flags`. Returns pointer to page-aligned beginning of the allocated buffer.
|
||||
The actual requested `baseaddr` will be located at
|
||||
`ret + baseaddr % pagesize`.
|
||||
|
||||
- `struct kvm_cpuid2 *tst_kvm_get_cpuid(int sysfd)` – Get a list of supported
|
||||
virtual CPU features returned by `ioctl(KVM_GET_SUPPORTED_CPUID)`.
|
||||
The argument must be an open file descriptor returned by `open("/dev/kvm")`.
|
||||
|
||||
- `void tst_kvm_create_instance(struct tst_kvm_instance *inst,
|
||||
size_t ram_size)` – Creates and fully initializes a new KVM virtual machine
|
||||
with at least `ram_size` bytes of memory. The VM instance info will be
|
||||
stored in `inst`.
|
||||
|
||||
- `int tst_kvm_run_instance(struct tst_kvm_instance *inst, int exp_errno)` –
|
||||
Executes the program installed in KVM virtual machine `inst`. Any result
|
||||
messages returned by the VM will be automatically printed to controller
|
||||
program output. Returns zero. If `exp_errno` is non-zero, the VM execution
|
||||
syscall is allowed to fail with the `exp_errno` error code and
|
||||
`tst_kvm_run_instance()` will return -1 instead of terminating the test.
|
||||
|
||||
- `void tst_kvm_destroy_instance(struct tst_kvm_instance *inst)` – Deletes
|
||||
the KVM virtual machine `inst`. Note that the guarded buffers assigned
|
||||
to the VM by `tst_kvm_create_instance()` or `tst_kvm_alloc_memory()` will
|
||||
not be freed.
|
||||
|
||||
The KVM host library does not provide any way to reset a VM instance back
|
||||
to initial state. Running multiple iterations of the test requires destroying
|
||||
the old VM instance and creating a new one. Otherwise the VM will exit
|
||||
without reporting any results on the second iteration and the test will fail.
|
||||
The `tst_kvm_run()` function handles this issue correctly.
|
||||
|
||||
3. KVM guest library
|
||||
--------------------
|
||||
|
||||
The KVM guest library provides a minimal implementation of both the LTP
|
||||
test library and the standard C library functions. Do not try to include
|
||||
the usual LTP or C headers in guest payload code, it will not work.
|
||||
|
||||
3.1 Standard C functions
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
`#include "kvm_test.h"`
|
||||
|
||||
The functions listed below are implemented according to the C standard:
|
||||
|
||||
- `void *memset(void *dest, int val, size_t size)`
|
||||
- `void *memzero(void *dest, size_t size)`
|
||||
- `void *memcpy(void *dest, const void *src, size_t size)`
|
||||
- `char *strcpy(char *dest, const char *src)`
|
||||
- `char *strcat(char *dest, const char *src)`
|
||||
- `size_t strlen(const char *str)`
|
||||
|
||||
3.2 LTP library functions
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
`#include "kvm_test.h"`
|
||||
|
||||
The KVM guest library currently provides the LTP functions for reporting test
|
||||
results. All standard result flags except for `T*ERRNO` are supported
|
||||
with the same rules as usual. However, the printf-like formatting is not
|
||||
implemented yet.
|
||||
|
||||
- `void tst_res(int result, const char *message)`
|
||||
- `void tst_brk(int result, const char *message) __attribute__((noreturn))`
|
||||
|
||||
A handful of useful macros is also available:
|
||||
|
||||
- `TST_TEST_TCONF(message)` – Generates a test program that will simply print
|
||||
a `TCONF` message and exit. This is useful when the real test cannot be
|
||||
built due to missing dependencies or arch limitations.
|
||||
|
||||
- `ARRAY_SIZE(arr)` – Returns the number of items in statically allocated
|
||||
array `arr`.
|
||||
|
||||
- `LTP_ALIGN(x, a)` – Aligns integer `x` to be a multiple of `a`, which
|
||||
must be a power of 2.
|
||||
|
||||
3.3 Arch independent functions
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
`#include "kvm_test.h"`
|
||||
|
||||
Memory management in KVM guest library currently uses only primitive linear
|
||||
buffer for memory allocation. There are no checks whether the VM can allocate
|
||||
more memory and the already allocated memory cannot be freed.
|
||||
|
||||
- `void *tst_heap_alloc(size_t size)` – Allocates a block of memory on the heap.
|
||||
|
||||
- `void *tst_heap_alloc_aligned(size_t size, size_t align)` – Allocates
|
||||
a block of memory on the heap with the starting address aligned to given
|
||||
value.
|
||||
|
||||
3.4 x86 specific functions
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
`#include "kvm_test.h"` +
|
||||
`#include "kvm_x86.h"`
|
||||
|
||||
- `struct kvm_interrupt_frame` – Opaque arch-dependent structure which holds
|
||||
interrupt frame information. Use the functions below to get individual values:
|
||||
|
||||
- `uintptr_t kvm_get_interrupt_ip(const struct kvm_interrupt_frame *ifrm)` –
|
||||
Get instruction pointer value from interrupt frame structure. This may be
|
||||
the instruction which caused an interrupt or the one immediately after,
|
||||
depending on the interrupt vector semantics.
|
||||
|
||||
- `int (*tst_interrupt_callback)(void *userdata,
|
||||
struct kvm_interrupt_frame *ifrm, unsigned long errcode)` – Interrupt handler
|
||||
callback prototype. When an interrupt occurs, the assigned callback function
|
||||
will be passed the `userdata` pointer that was given
|
||||
to `tst_set_interrupt_callback()`, interrupt frame `ifrm` and the error
|
||||
code `errcode` defined by the interrupt vector semantics. If the interrupt
|
||||
vector does not generate an error code, `errcode` will be set to zero.
|
||||
The callback function must return 0 if the interrupt was successfully
|
||||
handled and test execution should resume. Non-zero return value means that
|
||||
the interrupt could not be handled and the test will terminate with error.
|
||||
|
||||
- `void tst_set_interrupt_callback(unsigned int vector,
|
||||
tst_interrupt_callback func, void *userdata)` – Register new interrupt
|
||||
handler callback function `func` for interrupt `vector`. The `userdata`
|
||||
argument is an arbitrary pointer that will be passed to `func()` every time
|
||||
it gets called. The previous interrupt handler callback will be removed.
|
||||
Setting `func` to `NULL` will remove any existing interrupt handler
|
||||
from `vector` and the interrupt will become fatal error.
|
||||
|
||||
[source,c]
|
||||
-------------------------------------------------------------------------------
|
||||
struct page_table_entry_pae {
|
||||
unsigned int present: 1;
|
||||
unsigned int writable: 1;
|
||||
unsigned int user_access: 1;
|
||||
unsigned int write_through: 1;
|
||||
unsigned int disable_cache: 1;
|
||||
unsigned int accessed: 1;
|
||||
unsigned int dirty: 1;
|
||||
unsigned int page_type: 1;
|
||||
unsigned int global: 1;
|
||||
unsigned int padding: 3;
|
||||
uint64_t address: 40;
|
||||
unsigned int padding2: 7;
|
||||
unsigned int prot_key: 4;
|
||||
unsigned int noexec: 1;
|
||||
} __attribute__((__packed__));
|
||||
|
||||
struct kvm_cpuid {
|
||||
unsigned int eax, ebx, ecx, edx;
|
||||
};
|
||||
|
||||
struct kvm_cregs {
|
||||
unsigned long cr0, cr2, cr3, cr4;
|
||||
};
|
||||
|
||||
struct kvm_sregs {
|
||||
uint16_t cs, ds, es, fs, gs, ss;
|
||||
};
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
`struct page_table_entry_pae` is the page table entry structure for PAE and
|
||||
64bit paging modes. See Intel(R) 64 and IA-32 Architectures Software
|
||||
Developer's Manual, Volume 3, Chapter 4 for explanation of the fields.
|
||||
|
||||
- `uintptr_t kvm_get_page_address_pae(const struct page_table_entry_pae *entry)`
|
||||
– Returns the physical address of the memory page referenced by the given
|
||||
page table `entry`. Depending on memory mapping changes done by the test,
|
||||
the physical address may not be a valid pointer. The caller must determine
|
||||
whether the address points to another page table entry or a data page, using
|
||||
the known position in page table hierarchy and `entry->page_type`. Returns
|
||||
zero if the `entry` does not reference any memory page.
|
||||
|
||||
- `void kvm_set_segment_descriptor(struct segment_descriptor *dst, uint64_t baseaddr, uint32_t limit, unsigned int flags)` -
|
||||
Fill the `dst` segment descriptor with given values. The maximum value
|
||||
of `limit` is `0xfffff` (inclusive) regardless of `flags`.
|
||||
|
||||
- `void kvm_parse_segment_descriptor(struct segment_descriptor *src, uint64_t *baseaddr, uint32_t *limit, unsigned int *flags)` -
|
||||
Parse data in the `src` segment descriptor and copy them to variables
|
||||
pointed to by the other arguments. Any parameter except the first one can
|
||||
be `NULL`.
|
||||
|
||||
- `int kvm_find_free_descriptor(const struct segment_descriptor *table, size_t size)` -
|
||||
Find the first segment descriptor in `table` which does not have
|
||||
the `SEGFLAG_PRESENT` bit set. The function handles double-size descriptors
|
||||
correctly. Returns index of the first available descriptor or -1 if all
|
||||
`size` descriptors are taken.
|
||||
|
||||
- `unsigned int kvm_create_stack_descriptor(struct segment_descriptor *table, size_t tabsize, void *stack_base)` -
|
||||
Convenience function for registering a stack segment descriptor. It'll
|
||||
automatically find a free slot in `table` and fill the necessary flags.
|
||||
The `stack_base` pointer must point to the bottom of the stack.
|
||||
|
||||
- `void kvm_get_cpuid(unsigned int eax, unsigned int ecx,
|
||||
struct kvm_cpuid *buf)` – Executes the CPUID instruction with the given
|
||||
`eax` and `ecx` arguments and stores the results in `buf`.
|
||||
|
||||
- `void kvm_read_cregs(struct kvm_cregs *buf)` – Copies the current values
|
||||
of control registers to `buf`.
|
||||
|
||||
- `void kvm_read_sregs(struct kvm_sregs *buf)` - Copies the current values
|
||||
of segment registers to `buf`.
|
||||
|
||||
- `uint64_t kvm_rdmsr(unsigned int msr)` – Returns the current value
|
||||
of model-specific register `msr`.
|
||||
|
||||
- `void kvm_wrmsr(unsigned int msr, uint64_t value)` – Stores `value`
|
||||
into model-specific register `msr`.
|
||||
|
||||
- `void kvm_exit(void) __attribute__((noreturn))` – Terminate the test.
|
||||
Similar to calling `exit(0)` in a regular LTP test, although `kvm_exit()`
|
||||
will terminate only one iteration of the test, not the whole host process.
|
||||
|
||||
See Intel(R) 64 and IA-32 Architectures Software Developer's Manual
|
||||
for documentation of standard and model-specific x86 registers.
|
||||
|
||||
3.5 AMD SVM helper functions
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
`#include "kvm_test.h"` +
|
||||
`#include "kvm_x86.h"` +
|
||||
`#include "kvm_x86_svm.h"`
|
||||
|
||||
The KVM guest library provides basic helper functions for creating and running
|
||||
nested virtual machines using the AMD SVM technology.
|
||||
|
||||
.Example code to execute nested VM
|
||||
[source,c]
|
||||
-------------------------------------------------------------------------------
|
||||
int guest_main(void)
|
||||
{
|
||||
...
|
||||
return 0;
|
||||
}
|
||||
|
||||
void main(void)
|
||||
{
|
||||
struct kvm_svm_vcpu *vm;
|
||||
|
||||
kvm_init_svm();
|
||||
vm = kvm_create_svm_vcpu(guest_main, 1);
|
||||
kvm_svm_vmrun(vm);
|
||||
}
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
- `int kvm_is_svm_supported(void)` - Returns non-zero value if the CPU
|
||||
supports AMD SVM, otherwise returns 0.
|
||||
|
||||
- `int kvm_get_svm_state(void)` - Returns non-zero value if SVM is currently
|
||||
enabled, otherwise returns 0.
|
||||
|
||||
- `void kvm_set_svm_state(int enabled)` - Enable or disable SVM according
|
||||
to argument. If SVM is disabled by host or not supported, the test will exit
|
||||
with `TCONF`.
|
||||
|
||||
- `void kvm_init_svm(void)` - Enable and fully initialize SVM, including
|
||||
allocating and setting up host save area VMCB. If SVM is disabled by host or
|
||||
not supported, the test will exit with `TCONF`.
|
||||
|
||||
- `struct kvm_vmcb *kvm_alloc_vmcb(void)` - Allocate new VMCB structure
|
||||
with correct memory alignment and fill it with zeroes.
|
||||
|
||||
- `void kvm_vmcb_set_intercept(struct kvm_vmcb *vmcb, unsigned int id, unsigned int state)` -
|
||||
Set SVM intercept bit `id` to given `state`.
|
||||
|
||||
- `void kvm_init_guest_vmcb(struct kvm_vmcb *vmcb, uint32_t asid, uint16_t ss, void *rsp, int (*guest_main)(void))` -
|
||||
Initialize new SVM virtual machine. The `asid` parameter is the nested
|
||||
page table ID. The `ss` and `rsp` parameters set the stack segment and stack
|
||||
pointer values, respectively. The `guest_main` parameter sets the code entry
|
||||
point of the virtual machine. All control registers, segment registers
|
||||
(except stack segment register), GDTR and IDTR will be copied
|
||||
from the current CPU state.
|
||||
|
||||
- `struct kvm_svm_vcpu *kvm_create_svm_vcpu(int (*guest_main)(void), int alloc_stack)` -
|
||||
Convenience function for allocating and initializing new SVM virtual CPU.
|
||||
The `guest_main` parameter is passed to `kvm_init_guest_vmcb()`,
|
||||
the `alloc_stack` parameter controls whether a new 8KB stack will be
|
||||
allocated and registered in GDT. Interception will be enabled for `VMSAVE`
|
||||
and `HLT` instructions. If you set `alloc_stack` to zero, you must configure
|
||||
the stack segment register and stack pointer manually.
|
||||
|
||||
- `void kvm_svm_vmrun(struct kvm_svm_vcpu *cpu)` - Start or continue execution
|
||||
of a nested virtual machine. Beware that FPU state is not saved. Do not use
|
||||
floating point types or values in nested guest code. Also do not use
|
||||
`tst_res()` or `tst_brk()` functions in nested guest code.
|
||||
|
||||
See AMD64 Architecture Programmer's Manual Volume 2 for documentation
|
||||
of the Secure Virtual Machine (SVM) technology.
|
||||
|
||||
4. KVM guest environment
|
||||
------------------------
|
||||
|
||||
KVM guest payload execution begins with bootstrap code which will perform
|
||||
the minimal guest environment setup required for running C code:
|
||||
|
||||
- Activate the appropriate CPU execution mode (IA-32 protected mode
|
||||
on 32-bit x86 or the 64-bit mode on x86_64).
|
||||
- Create indentity mapping (virtual address = physical address) of the lower
|
||||
2GB memory region, even if parts of the region are not backed by any host
|
||||
memory buffers. The memory region above 2GB threshold is left unmapped
|
||||
except for one memory page reserved for the `struct tst_kvm_result` buffer.
|
||||
- Initialize 8KB stack.
|
||||
- Install default interrupt handlers for standard CPU exception vectors.
|
||||
|
||||
When the environment setup is complete, bootstrap will call `void main(void)`
|
||||
function implemented by the test program. To finish execution of guest payload,
|
||||
the test can either return from the `main()` function or call `kvm_exit()`
|
||||
at any point.
|
||||
@@ -1,84 +0,0 @@
|
||||
LTP Library API Writing Guidelines
|
||||
==================================
|
||||
|
||||
NOTE: See also
|
||||
https://github.com/linux-test-project/ltp/wiki/Test-Writing-Guidelines[Test Writing Guidelines],
|
||||
https://github.com/linux-test-project/ltp/wiki/C-Test-API[C Test API],
|
||||
https://github.com/linux-test-project/ltp/wiki/Shell-Test-API[Shell Test API].
|
||||
|
||||
1. General Rules
|
||||
----------------
|
||||
|
||||
For extending library API it applies the same general rules as for writing tests,
|
||||
(see https://github.com/linux-test-project/ltp/wiki/Test-Writing-Guidelines[Test Writing Guidelines],
|
||||
offline: 'doc/test-writing-guidelines.txt'),
|
||||
with strong focus on readability and simplicity.
|
||||
|
||||
Library tests are in 'lib/newlib_tests' directory.
|
||||
|
||||
Don't forget to update docs when you change the API.
|
||||
|
||||
Environment variables should be listed in
|
||||
https://github.com/linux-test-project/ltp/wiki/User-Guidelines[LTP User Guidelines]
|
||||
and in help output (`-h`) for both C and shell API.
|
||||
|
||||
2. C API
|
||||
--------
|
||||
|
||||
2.1 LTP-001: Sources have tst_ prefix
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
API source code is in headers in 'include/{empty}*.h', 'include/lapi/{empty}*.h'
|
||||
(backward compatibility for old kernel and libc) and C sources in 'lib/{empty}*.c'.
|
||||
Files have `tst_` prefix.
|
||||
|
||||
2.2 LTP-002: TST_RET and TST_ERR are not modified
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The test author is guaranteed that the test API will not modify these
|
||||
variables. This prevents silent errors where the return value and
|
||||
errno are overwritten before the test has chance to check them.
|
||||
|
||||
The macros which are clearly intended to update these variables. That
|
||||
is `TEST` and those in 'tst_test_macros.h'. Are of course allowed to
|
||||
update these variables.
|
||||
|
||||
2.3 LTP-003: Externally visible library symbols have the tst_ prefix
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Functions, types and variables in the public test API should have the
|
||||
tst_ prefix. With some exceptions for symbols already prefixed with
|
||||
`safe_` or `ltp_`.
|
||||
|
||||
Static (private) symbols should not have the prefix.
|
||||
|
||||
|
||||
3. Shell API
|
||||
------------
|
||||
|
||||
API source code is in 'tst_test.sh', 'tst_security.sh' and 'tst_net.sh'
|
||||
(all in 'testcases/lib' directory).
|
||||
|
||||
Changes in the shell API should not introduce uncommon dependencies
|
||||
(use basic commands installed everywhere by default).
|
||||
|
||||
3.1 Shell libraries
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Aside from shell API libraries in 'testcases/lib', it's worth putting
|
||||
common code for a group of tests into a shell library. The filename
|
||||
should end with '_lib.sh' and the library should load 'tst_test.sh' or
|
||||
'tst_net.sh'.
|
||||
|
||||
Shell libraries should have conditional expansion for 'TST_SETUP' or 'TST_CLEANUP',
|
||||
to avoid surprises when test specific setup/cleanup function is redefined by
|
||||
shell library.
|
||||
|
||||
[source,sh]
|
||||
-------------------------------------------------------------------------------
|
||||
# ipsec_lib.sh
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
TST_SETUP="${TST_SETUP:-ipsec_lib_setup}"
|
||||
...
|
||||
. tst_test.sh
|
||||
-------------------------------------------------------------------------------
|
||||
@@ -1,170 +0,0 @@
|
||||
LTP Release Procedure
|
||||
=====================
|
||||
|
||||
1. Release preparations
|
||||
-----------------------
|
||||
|
||||
The release procedure generally takes a few weeks. In the first week or two,
|
||||
patches that should go into the release are reviewed and possibly merged. These
|
||||
patches are either fixes or patches pointed out by the community.
|
||||
|
||||
Patch review, when finished, is followed by a git freeze, which is a period
|
||||
where only fixes are pushed to the git. During that period community is
|
||||
expected to run a LTP pre-release tests, reports problems, and/or send fixes to
|
||||
the mailing list. In this period we are especially making sure that there are
|
||||
no regressions in the test results on a wide range of distributions and
|
||||
architectures.
|
||||
|
||||
Once the stabilization period has ended the time has finally come to proceed
|
||||
with the release.
|
||||
|
||||
2. Prepare the release notes
|
||||
----------------------------
|
||||
|
||||
Part of the preparation is also to write the release notes, which are then
|
||||
added to the GitHub release and also sent as announcement to various mailing
|
||||
lists (see below).
|
||||
|
||||
Have a look at https://lore.kernel.org/ltp/ZGNiQ1sMGvPU_ETp@yuki/ to get the
|
||||
idea how it should look.
|
||||
|
||||
3. Tag the git and push changes to github
|
||||
-----------------------------------------
|
||||
|
||||
[source,sh]
|
||||
--------------------------------------------------------------------
|
||||
cd ltp
|
||||
echo YYYYMMDD > VERSION
|
||||
git commit -S -s -m 'LTP YYYYMMDD' VERSION
|
||||
git tag -s -a YYYYMMDD -m 'LTP YYYYMMDD'
|
||||
git push origin master:master
|
||||
git push origin YYYYMMDD
|
||||
--------------------------------------------------------------------
|
||||
|
||||
NOTE: The string YYYYMMDD should be substituted to the current date.
|
||||
|
||||
NOTE: You can use './tools/tag-release.sh' script to have the above automated.
|
||||
It allows you to verify the tag before pushing it and does other checks.
|
||||
|
||||
[source,sh]
|
||||
--------------------------------------------------------------------
|
||||
$ ./tools/tag-release.sh
|
||||
===== git push =====
|
||||
new tag: 'YYYYMMDD', previous tag: '20230127'
|
||||
tag YYYYMMDD
|
||||
Tagger: Person-who-released LTP <foo@example.com>
|
||||
Date: ...
|
||||
|
||||
LTP YYYYMMDD
|
||||
-----BEGIN PGP SIGNATURE-----
|
||||
...
|
||||
-----END PGP SIGNATURE-----
|
||||
|
||||
commit 3ebc2dfa85c2445bb68d8c0d66e33c4da1e1b3a7
|
||||
gpg: using RSA key ...
|
||||
...
|
||||
Primary key fingerprint: ...
|
||||
Author: Person-who-released LTP <foo@example.com>
|
||||
Date: ...
|
||||
|
||||
LTP YYYYMMDD
|
||||
|
||||
Signed-off-by: Person-who-released LTP <foo@example.com>
|
||||
|
||||
diff --git a/VERSION b/VERSION
|
||||
index af4c41fec..ae488c0e7 100644
|
||||
--- a/VERSION
|
||||
+++ b/VERSION
|
||||
@@ -1 +1 @@
|
||||
-20230127
|
||||
+YYYYMMDD
|
||||
|
||||
Please check tag and signature. Proceed? [N/y]: y
|
||||
Pushing changes to upstream git. Proceed? [N/y]: y
|
||||
...
|
||||
To github.com:linux-test-project/ltp.git
|
||||
* [new tag] YYYYMMDD -> YYYYMMDD
|
||||
--------------------------------------------------------------------
|
||||
|
||||
4. Prepare tarballs and metadata documentation
|
||||
----------------------------------------------
|
||||
|
||||
[source,sh]
|
||||
--------------------------------------------------------------------
|
||||
# clone already clonned git repository to new folder
|
||||
cd ..
|
||||
git clone ltp ltp-full-YYYYMMDD
|
||||
cd ltp-full-YYYYMMDD
|
||||
|
||||
# update all submodules
|
||||
git submodule update --init
|
||||
|
||||
# Generate configure script
|
||||
make autotools
|
||||
|
||||
# Generate tarballs
|
||||
cd ..
|
||||
tar -cjf ltp-full-YYYYMMDD.tar.bz2 ltp-full-YYYYMMDD --exclude .git
|
||||
tar -cJf ltp-full-YYYYMMDD.tar.xz ltp-full-YYYYMMDD --exclude .git
|
||||
|
||||
# Generate checksums
|
||||
md5 ltp-full-YYYYMMDD.tar.xz > ltp-full-YYYYMMDD.tar.xz.md5
|
||||
sha1 ltp-full-YYYYMMDD.tar.xz > ltp-full-YYYYMMDD.tar.xz.sha1
|
||||
sha256sum ltp-full-YYYYMMDD.tar.xz > ltp-full-YYYYMMDD.tar.xz.sha256
|
||||
|
||||
# Generate metadata documentation
|
||||
./configure --with-metadata-generator=asciidoctor
|
||||
make -C metadata
|
||||
cp -v docparse/metadata.html ../metadata.YYYYMMDD.html
|
||||
--------------------------------------------------------------------
|
||||
|
||||
NOTE: You can use './tools/create-tarballs-metadata.sh' script to have the
|
||||
above automated. All generated files are placed in ltp-release-YYYYMMDD
|
||||
directory.
|
||||
|
||||
[source,sh]
|
||||
--------------------------------------------------------------------
|
||||
$ ./tools/create-tarballs-metadata.sh
|
||||
===== git clone =====
|
||||
Cloning into 'ltp-full-YYYYMMDD'...
|
||||
done.
|
||||
===== Update submodules =====
|
||||
Submodule 'tools/kirk' (https://github.com/linux-test-project/kirk.git) registered for path 'tools/kirk'
|
||||
...
|
||||
===== Generate configure script =====
|
||||
sed -n '1{s:LTP-:m4_define([LTP_VERSION],[:;s:$:]):;p;q}' VERSION > m4/ltp-version.m4
|
||||
aclocal -I m4
|
||||
...
|
||||
===== Generate tarballs =====
|
||||
===== Generate checksums =====
|
||||
===== Generate metadata documentation =====
|
||||
checking for a BSD-compatible install... /usr/bin/install -c
|
||||
...
|
||||
'docparse/metadata.html' -> '/home/foo/ltp-release-YYYYMMDD/metadata.YYYYMMDD.html'
|
||||
Generated files are in '/home/foo/ltp-release-YYYYMMDD', upload them to github
|
||||
--------------------------------------------------------------------
|
||||
|
||||
5. Upload the generated files to GitHub
|
||||
---------------------------------------
|
||||
|
||||
Click on https://github.com/linux-test-project/ltp/releases['Releases'] then
|
||||
switch to https://github.com/linux-test-project/ltp/tags['Tags'], then click on
|
||||
'Add release notes'. There should be 'Attach binaries ...' link at the
|
||||
bottom of the page.
|
||||
|
||||
Don't forget to upload checksums for the tarballs and metadata documentation as well.
|
||||
|
||||
5. Send release announcement
|
||||
----------------------------
|
||||
|
||||
The announcement is sent to:
|
||||
|
||||
* ltp at lists.linux.it
|
||||
* linux-kernel at vger.kernel.org
|
||||
* libc-alpha at sourceware.org
|
||||
|
||||
CCed to:
|
||||
|
||||
* lwn at lwn.net
|
||||
* akpm at linux-foundation.org
|
||||
* torvalds at linux-foundation.org
|
||||
@@ -1,141 +0,0 @@
|
||||
# Patch Review
|
||||
|
||||
Anyone can and should review patches. It's the only way to get good at
|
||||
patch review and for the project to scale.
|
||||
|
||||
## Goals of patch review
|
||||
|
||||
1. Prevent false positive test results
|
||||
2. Prevent false negative test results
|
||||
3. Keep the code as simple as possible, but no simpler
|
||||
|
||||
## How to find clear errors
|
||||
|
||||
A clear error is one where there is unlikely to be any argument if you
|
||||
provide evidence of it. Evidence being an error trace or logical proof
|
||||
that an error will occur in a common situation.
|
||||
|
||||
The following are examples and may not be appropriate for all tests.
|
||||
|
||||
* Merge the patch locally. It should apply cleanly to master.
|
||||
* Compile the patch with default and non-default configurations.
|
||||
- Use sanitizers e.g. undefined behaviour, address.
|
||||
- Compile on non-x86
|
||||
- Compile on x86 with -m32
|
||||
* Use `make check`
|
||||
* Run effected tests in a VM
|
||||
- Use single vCPU
|
||||
- Use many vCPUs and enable NUMA
|
||||
- Restrict RAM to < 1GB.
|
||||
* Run effected tests on an embedded device
|
||||
* Run effected tests on non-x86 machine in general
|
||||
* Run reproducers on a kernel where the bug is present
|
||||
* Run tests with "-i0"
|
||||
* Compare usage of system calls with man page descriptions
|
||||
* Compare usage of system calls with kernel code
|
||||
* Search the LTP library for existing helper functions
|
||||
|
||||
## How to find subtle errors
|
||||
|
||||
A subtle error is one where you can expect some argument because you
|
||||
do not have clear evidence of an error. It is best to state these as
|
||||
questions and not make assertions if possible.
|
||||
|
||||
Although if it is a matter of style or "taste" then senior maintainers
|
||||
can assert what is correct to avoid bike shedding.
|
||||
|
||||
* Ask what happens if there is an error, could it be debugged just
|
||||
with the test output?
|
||||
* Are we testing undefined behavior?
|
||||
- Could future kernel behaviour change without "breaking userland"?
|
||||
- Does the kernel behave differently depending on hardware?
|
||||
- Does it behave differently depending on kernel configuration?
|
||||
- Does it behave differently depending on the compiler?
|
||||
- Would it behave differently if the order of checks on syscall parameters
|
||||
changed in the kernel?
|
||||
* Will it scale to tiny and huge systems?
|
||||
- What happens if there are 100+ CPUs?
|
||||
- What happens if each CPU core is very slow?
|
||||
- What happens if there are 2TB of RAM?
|
||||
* Are we repeating a pattern that can be turned into a library function?
|
||||
* Is a single test trying to do too much?
|
||||
* Could multiple similar tests be merged?
|
||||
* Race conditions
|
||||
- What happens if a process gets preempted?
|
||||
- Could checkpoints or fuzzsync by used instead?
|
||||
- Note, usually you can insert a sleep to prove a race condition
|
||||
exists however finding them is hard
|
||||
* Is there a simpler way to achieve the same kernel coverage?
|
||||
|
||||
## How to get patches merged
|
||||
|
||||
Once you think a patch is good enough you should add your Reviewed-by
|
||||
and/or Tested-by tags. This means you will get some credit for getting
|
||||
the patch merged. Also some blame if there are problems.
|
||||
|
||||
If you ran the test you can add the Tested-by tag. If you read the
|
||||
code or used static analysis tools on it, you can add the Reviewed-by
|
||||
tag.
|
||||
|
||||
In addition you can expect others to review your patches and add their
|
||||
tags. This will speed up the process of getting your patches merged.
|
||||
|
||||
## Maintainers Checklist
|
||||
|
||||
Patchset should be tested locally and ideally also in maintainer's fork in
|
||||
GitHub Actions on GitHub.
|
||||
|
||||
NOTE: GitHub Actions do only build testing, passing the CI means only that
|
||||
the test compiles fine on variety of different distributions and releases.
|
||||
|
||||
The test should be executed at least once locally and should PASS as well.
|
||||
|
||||
Commit messages should have
|
||||
|
||||
* Author's `Signed-off-by` tag
|
||||
* Committer's `Reviewed-by` or `Signed-off-by` tag
|
||||
* Check also mailing lists for other reviewers / testers tags, notes and failure reports
|
||||
* `Fixes: hash` if it fixes particular LTP commit
|
||||
* `Fixes: #N` if it fixes github issue number N, so it's automatically closed
|
||||
|
||||
After patch is accepted or rejected, set correct state and archive in
|
||||
https://patchwork.ozlabs.org/project/ltp/list/[LTP patchwork instance].
|
||||
|
||||
Also update `.github/workflows/wiki-mirror.yml` script which mirrors
|
||||
`doc/*.txt` to LTP wiki (git URL https://github.com/linux-test-project/ltp.wiki.git)
|
||||
if new wiki page is added.
|
||||
|
||||
## New tests
|
||||
New test should
|
||||
|
||||
* Have a record in runtest file
|
||||
* Test should work fine with more than one iteration
|
||||
(e.g. run with `-i 100`)
|
||||
* Run with `-i 0` to check that setup and cleanup are coded properly (no test is being run)
|
||||
* Have a brief description
|
||||
* License: the default license for new tests is GPL v2 or later, use
|
||||
GPL-2.0-or-later; the licence for test (e.g. GPL-2.0) should not change
|
||||
unless test is completely rewritten
|
||||
* Old copyrights should be kept unless test is completely rewritten
|
||||
|
||||
### C tests
|
||||
* Use new https://github.com/linux-test-project/ltp/wiki/Test-Writing-Guidelines#22-writing-a-test-in-c[C API]
|
||||
* Test binaries are added into corresponding `.gitignore` files
|
||||
* Check coding style with `make check`
|
||||
(more in https://github.com/linux-test-project/ltp/wiki/Test-Writing-Guidelines#21-c-coding-style[C coding style])
|
||||
* Docparse documentation
|
||||
* If a test is a regression test it should include tags
|
||||
(more in https://github.com/linux-test-project/ltp/wiki/Test-Writing-Guidelines#2238-test-tags[Test tags])
|
||||
* When rewriting old tests, https://en.wikipedia.org/wiki/%CE%9CClinux[uClinux]
|
||||
support should be removed (project has been discontinued).
|
||||
E.g. remove `#ifdef UCLINUX`, replace `FORK_OR_VFORK()` with simple `fork()` or `SAFE_FORK()`.
|
||||
|
||||
### Shell tests
|
||||
* Use new https://github.com/linux-test-project/ltp/wiki/Test-Writing-Guidelines#23-writing-a-testcase-in-shell[shell API]
|
||||
* Check coding style with `make check`
|
||||
(more in https://github.com/linux-test-project/ltp/wiki/Test-Writing-Guidelines#132-shell-coding-style[Shell coding style])
|
||||
* If a test is a regression test it should include related kernel or glibc commits as a comment
|
||||
|
||||
## LTP library
|
||||
For patchset touching library please check also
|
||||
https://github.com/linux-test-project/ltp/wiki/LTP-Library-API-Writing-Guidelines[LTP Library API Writing Guidelines].
|
||||
+31
-5
@@ -1,11 +1,37 @@
|
||||
# Copyright (c) Linux Test Project, 2024-2025
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
# Copyright (C) 2009, Cisco Systems Inc.
|
||||
# Ngie Cooper, July 2009
|
||||
|
||||
top_srcdir ?= ..
|
||||
top_srcdir ?= ..
|
||||
|
||||
include $(top_srcdir)/include/mk/env_pre.mk
|
||||
|
||||
RECURSIVE_TARGETS := install
|
||||
PYTHON := python3
|
||||
VENV_DIR := .venv
|
||||
|
||||
include $(top_srcdir)/include/mk/generic_trunk_target.mk
|
||||
# only fish and bash/zsh supported
|
||||
VENV_CMD := if [ "x${FISH_VERSION}" != "x" ]; then . $(VENV_DIR)/bin/activate.fish; else . $(VENV_DIR)/bin/activate; fi
|
||||
|
||||
RUN_VENV := if [ -d $(VENV_DIR) ]; then $(VENV_CMD); fi
|
||||
|
||||
$(VENV_DIR):
|
||||
$(PYTHON) -m virtualenv $(VENV_DIR)
|
||||
$(VENV_CMD) && pip install -r requirements.txt
|
||||
|
||||
.PHONY: setup
|
||||
setup: $(VENV_DIR)
|
||||
|
||||
${abs_top_builddir}/metadata/ltp.json:
|
||||
$(MAKE) -C ${abs_top_builddir}/metadata
|
||||
|
||||
all: ${abs_top_builddir}/metadata/ltp.json
|
||||
$(RUN_VENV); sphinx-build -v -b html . html
|
||||
|
||||
spelling:
|
||||
$(RUN_VENV); sphinx-build -b spelling -d build/doctree . build/spelling
|
||||
|
||||
clean:
|
||||
rm -rf html/ build/ _static/syscalls.rst _static/tests.rst syscalls.tbl \
|
||||
${abs_top_builddir}/metadata/ltp.json
|
||||
|
||||
distclean: clean
|
||||
rm -rf $(VENV_DIR)
|
||||
|
||||
@@ -1,77 +0,0 @@
|
||||
Supported kernel, libc, toolchain versions
|
||||
==========================================
|
||||
|
||||
1. Build testing with GitHub Actions
|
||||
------------------------------------
|
||||
|
||||
We test master branch in https://github.com/linux-test-project/ltp/actions[GitHub Actions]
|
||||
to ensure LTP builds on various distributions including old, current and bleeding edge.
|
||||
We test both gcc and clang toolchains, various architectures with cross-compilation.
|
||||
For list of tested distros see
|
||||
https://github.com/linux-test-project/ltp/blob/master/.github/workflows/ci.yml[.github/workflows/ci.yml].
|
||||
|
||||
|
||||
NOTE: GitHub Actions does only build testing, passing the CI means only that
|
||||
the test compiles fine on variety of different distributions and releases.
|
||||
GitHub Actions also uses the latest distribution image of a particular release.
|
||||
|
||||
1.1 Oldest tested distributions
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
[align="center",options="header"]
|
||||
|==============================================================
|
||||
| Distro | kernel | glibc | gcc | clang
|
||||
| CentOS 7 | 3.10 | 2.17 | 4.8.5 | -
|
||||
| Ubuntu 18.04 LTS bionic | 4.15 | 2.27 | 7.3.0 | -
|
||||
| Debian 10 oldstable (buster) | 4.19.37 | 2.28 | 8.3.0 | 7.0
|
||||
|==============================================================
|
||||
|
||||
Older distributions are not officially supported, which means that it
|
||||
may or may not work. It all depends on your luck. It should be possible
|
||||
to compile latest LTP even on slightly older distributions than we
|
||||
support with a few manual tweaks, e.g. disabling manually tests for
|
||||
newly added syscalls, etc. Trivial fixes/workarounds may be accepted,
|
||||
but users are encouraged to move to a newer distro.
|
||||
|
||||
If latest LTP cannot be compiled even with some amount of workarounds,
|
||||
you may result to older LTP releases, however these are _not_ supported
|
||||
in any way. Also if you are trying to run LTP on more than 10 years old
|
||||
distribution you may as well reconsider you life choices.
|
||||
|
||||
1.2 Tested architectures
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
[align="center",options="header"]
|
||||
|==================================
|
||||
| arch | build
|
||||
| x86_64 | native
|
||||
| x86 emulation | native
|
||||
| aarch64 | cross compilation
|
||||
| ppc64le | cross compilation
|
||||
| s390x | cross compilation
|
||||
|==================================
|
||||
|
||||
1.3 Minimal supported kernel version
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Minimal supported kernel version is 3.10.
|
||||
|
||||
1.4 Supported libc
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
[align="center",options="header"]
|
||||
|==================================
|
||||
| Libc | Note
|
||||
| https://www.gnu.org/software/libc/[GNU C Library (glibc)] | Targeted libc, tested both compilation and actual test results.
|
||||
| https://uclibc-ng.org/[uClibc-ng] | Although not being tested it should work as well as it attempt to maintain a glibc compatible interface.
|
||||
| https://www.uclibc.org/[uClibc] | Older https://www.uclibc.org/[uClibc] might have problems.
|
||||
| https://musl.libc.org/[musl] | Not yet fully supported (see
|
||||
https://github.com/linux-test-project/ltp/blob/master/ci/alpine.sh[CI script]
|
||||
for list of files which need to be deleted in order to compile under musl).
|
||||
| binder (Android) | Please use https://android.googlesource.com/platform/external/ltp/[AOSP fork].
|
||||
|==================================
|
||||
|
||||
1.5 Used C standard
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
LTP compiles with '-std=gnu99'.
|
||||
@@ -1,412 +0,0 @@
|
||||
LTP Test Writing Guidelines
|
||||
===========================
|
||||
|
||||
This document describes LTP guidelines and is intended for anybody who want to
|
||||
write or modify a LTP testcase. It's not a definitive guide and it's not, by
|
||||
any means, a substitute for common sense.
|
||||
|
||||
NOTE: See also
|
||||
https://github.com/linux-test-project/ltp/wiki/C-Test-API[C Test API],
|
||||
https://github.com/linux-test-project/ltp/wiki/Shell-Test-API[Shell Test API],
|
||||
https://github.com/linux-test-project/ltp/wiki/LTP-Library-API-Writing-Guidelines[LTP Library API Writing Guidelines].
|
||||
|
||||
Rules and recommendations which are "machine checkable" should be
|
||||
tagged with an ID like +LTP-XXX+. There will be a corresponding entry
|
||||
in
|
||||
https://github.com/linux-test-project/ltp/tree/master/doc/rules.tsv[doc/rules.tsv]. When
|
||||
you run 'make check' or 'make check-test' it will display these IDs as
|
||||
a reference.
|
||||
|
||||
1. Guide to clean and understandable code
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
For testcases it's required that the source code is as easy to follow as
|
||||
possible. When a test starts to fail the failure has to be analyzed, clean
|
||||
test codebase makes this task much easier and quicker.
|
||||
|
||||
Here are some hints on how to write clean and understandable code, a few of
|
||||
these points are further discussed below:
|
||||
|
||||
* First of all *Keep things simple*
|
||||
|
||||
* Keep function and variable names short but descriptive
|
||||
|
||||
* Keep functions reasonably short and focused on a single task
|
||||
|
||||
* Do not overcomment
|
||||
|
||||
* Be consistent
|
||||
|
||||
* Avoid deep nesting
|
||||
|
||||
* DRY
|
||||
|
||||
1.1 Keep things simple
|
||||
~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
For all it's worth keep the testcases simple or better as simple as possible.
|
||||
|
||||
The kernel and libc are tricky beasts and the complexity imposed by their
|
||||
interfaces is quite high. Concentrate on the interface you want to test and
|
||||
follow the UNIX philosophy.
|
||||
|
||||
It's a good idea to make the test as self-contained as possible too, ideally
|
||||
tests should not depend on tools or libraries that are not widely available.
|
||||
|
||||
Do not reinvent the wheel!
|
||||
|
||||
* Use LTP standard interface
|
||||
|
||||
* Do not add custom PASS/FAIL reporting functions
|
||||
|
||||
* Do not write Makefiles from scratch, use LTP build system instead
|
||||
|
||||
* Etc.
|
||||
|
||||
1.2 Keep functions and variable names short
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Choosing a good name for an API functions or even variables is a difficult
|
||||
task do not underestimate it.
|
||||
|
||||
There are a couple of customary names for different things that help people to
|
||||
understand code, for example:
|
||||
|
||||
* For loop variables are usually named with a single letter 'i', 'j', ...
|
||||
|
||||
* File descriptors 'fd' or 'fd_foo'.
|
||||
|
||||
* Number of bytes stored in file are usually named as 'size' or 'len'
|
||||
|
||||
* Etc.
|
||||
|
||||
1.3 Do not overcomment
|
||||
~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Comments can sometimes save you day but they can easily do more harm than
|
||||
good. There has been several cases where comments and actual implementation
|
||||
drifted slowly apart which yielded into API misuses and hard to find bugs.
|
||||
Remember there is only one thing worse than no documentation, wrong
|
||||
documentation.
|
||||
|
||||
Ideally everybody should write code that is obvious, which unfortunately isn't
|
||||
always possible. If there is a code that requires to be commented keep it
|
||||
short and to the point. These comments should explain *why* and not *how*
|
||||
things are done.
|
||||
|
||||
Never ever comment the obvious.
|
||||
|
||||
In case of LTP testcases it's customary to add an asciidoc formatted comment
|
||||
paragraph with highlevel test description at the beginning of the file right
|
||||
under the GPL SPDX header. This helps other people to understand the overall
|
||||
goal of the test before they dive into the technical details. It's also
|
||||
exported into generated documentation hence it should mostly explain what is
|
||||
tested.
|
||||
|
||||
1.4 DRY (Code duplication)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Copy & paste is a good servant but very poor master. If you are about to copy a
|
||||
large part of the code from one testcase to another, think what would happen if
|
||||
you find bug in the code that has been copied all around the tree. What about
|
||||
moving it to a library instead?
|
||||
|
||||
The same goes for short but complicated parts, whenever you are about to copy &
|
||||
paste a syscall wrapper that packs arguments accordingly to machine
|
||||
architecture or similarly complicated code, put it into a header instead.
|
||||
|
||||
2 Coding style
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
2.1 C coding style
|
||||
^^^^^^^^^^^^^^^^^^
|
||||
|
||||
LTP adopted Linux kernel coding style:
|
||||
https://www.kernel.org/doc/html/latest/process/coding-style.html
|
||||
|
||||
If you aren't familiar with its rules please read it, it's a well written
|
||||
introduction.
|
||||
|
||||
Run `make check` in the test's directory and/or use `make check-$TCID`,
|
||||
it uses (among other checks) our vendored version of
|
||||
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/plain/scripts/checkpatch.pl[checkpatch.pl]
|
||||
script from kernel git tree.
|
||||
|
||||
NOTE: If `make check` does not report any problems, the code still may be wrong
|
||||
as all tools used for checking only look for common mistakes.
|
||||
|
||||
2.1.1 LTP-004: Test executable symbols are marked static
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Test executables should not export symbols unnecessarily. This means
|
||||
that all top-level variables and functions should be marked with the
|
||||
static keyword. The only visible symbols should be those included from
|
||||
shared object files.
|
||||
|
||||
2.2 Shell coding style
|
||||
^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
When writing testcases in shell write in *portable shell* only, it's a good
|
||||
idea to try to run the test using alternative shell (alternative to bash, for
|
||||
example dash) too.
|
||||
|
||||
*Portable shell* means Shell Command Language as defined by POSIX with an
|
||||
exception of few widely used extensions, namely 'local' keyword used inside of
|
||||
functions and '-o' and '-a' test parameters (that are marked as obsolete in
|
||||
POSIX).
|
||||
|
||||
You can either try to run the testcases on Debian which has '/bin/sh' pointing
|
||||
to 'dash' by default or install 'dash' on your favorite distribution and use
|
||||
it to run the tests. If your distribution lacks 'dash' package you can always
|
||||
compile it from http://gondor.apana.org.au/~herbert/dash/files/[source].
|
||||
|
||||
Run `make check` in the test's directory and/or use `make check-$TCID.sh`,
|
||||
it uses (among other checks) our vendored version of
|
||||
https://salsa.debian.org/debian/devscripts/raw/master/scripts/checkbashisms.pl[checkbashism.pl]
|
||||
from Debian, that is used to check for non-portable shell code.
|
||||
|
||||
NOTE: If `make check` does not report any problems, the code still may be wrong
|
||||
as `checkbashisms.pl` used for checking only looks for common mistakes.
|
||||
|
||||
Here are some common sense style rules for shell
|
||||
|
||||
* Keep lines under 80 chars
|
||||
|
||||
* Use tabs for indentation
|
||||
|
||||
* Keep things simple, avoid unnecessary subshells
|
||||
|
||||
* Don't do confusing things (i.e. don't name your functions like common shell
|
||||
commands, etc.)
|
||||
|
||||
* Quote variables
|
||||
|
||||
* Be consistent
|
||||
|
||||
3 Backwards compatibility
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
LTP test should be as backward compatible as possible. Think of an enterprise
|
||||
distributions with long term support (more than five years since the initial
|
||||
release) or of an embedded platform that needs to use several years old
|
||||
toolchain supplied by the manufacturer.
|
||||
|
||||
Therefore LTP test for more current features should be able to cope with older
|
||||
systems. It should at least compile fine and if it's not appropriate for the
|
||||
configuration it should return 'TCONF'.
|
||||
|
||||
There are several types of checks we use:
|
||||
|
||||
The *configure script* is usually used to detect availability of a function
|
||||
declarations in system headers. It's used to disable tests at compile time or
|
||||
to enable fallback definitions.
|
||||
|
||||
Checking the *errno* value is another type of runtime check. Most of the
|
||||
syscalls returns either 'EINVAL' or 'ENOSYS' when syscall was not implemented
|
||||
or was disabled upon kernel compilation.
|
||||
|
||||
LTP has kernel version detection that can be used to disable tests at runtime,
|
||||
unfortunately kernel version does not always corresponds to a well defined
|
||||
feature set as distributions tend to backport hundreds of patches while the
|
||||
kernel version stays the same. Use with caution.
|
||||
|
||||
Lately we added kernel '.config' parser, a test can define a boolean
|
||||
expression of kernel config variables that has to be satisfied in order for a
|
||||
test to run. This is mostly used for kernel namespaces at the moment.
|
||||
|
||||
Sometimes it also makes sense to define a few macros instead of creating
|
||||
configure test. One example is Linux specific POSIX clock ids in
|
||||
'include/lapi/posix_clocks.h'.
|
||||
|
||||
3.1 Dealing with messed up legacy code
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
LTP still contains a lot of old and messy code and we are cleaning it up as
|
||||
fast as we can but despite the decade of efforts there is still a lot. If you
|
||||
start modifying old or a messy testcase and your changes are more complicated
|
||||
than simple typo fixes you should convert the test into a new library first.
|
||||
|
||||
It's also much easier to review the changes if you split them into a smaller
|
||||
logical groups. The same goes for moving files. If you need a rename or move
|
||||
file do it in a separate patch.
|
||||
|
||||
4 License
|
||||
~~~~~~~~~
|
||||
|
||||
Code contributed to LTP should be licensed under GPLv2+ (GNU GPL version 2 or
|
||||
any later version).
|
||||
|
||||
Use `SPDX-License-Identifier: GPL-2.0-or-later`
|
||||
|
||||
5 LTP Structure
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
The structure of LTP is quite simple. Each test is a binary written either in
|
||||
portable shell or C. The test gets a configuration via environment variables
|
||||
and/or command line parameters, it prints additional information into the
|
||||
stdout and reports overall success/failure via the exit value.
|
||||
|
||||
Tests are generally placed under the 'testcases/' directory. Everything that
|
||||
is a syscall or (slightly confusingly) libc syscall wrapper goes under
|
||||
'testcases/kernel/syscalls/'.
|
||||
|
||||
Then there is 'testcases/open_posix_testsuite/' which is a well maintained fork
|
||||
of the upstream project that has been dead since 2005 and also a number of
|
||||
directories with tests for more specific features.
|
||||
|
||||
5.1 Runtest Files
|
||||
^^^^^^^^^^^^^^^^^
|
||||
|
||||
The list of tests to be executed is stored in runtest files under the
|
||||
'runtest/' directory. The default set of runtest files to be executed is
|
||||
stored in 'scenario_groups/default'. When you add a test you should add
|
||||
corresponding entries into some runtest file(s) as well.
|
||||
|
||||
For syscall tests (these placed under 'testcases/kernel/syscalls/') use
|
||||
'runtest/syscalls' file, for kernel related tests for memory management we
|
||||
have 'runtest/mm', etc.
|
||||
|
||||
IMPORTANT: The runtest files should have one entry per a test. Creating a
|
||||
wrapper that runs all your tests and adding it as a single test
|
||||
into runtest file is strongly discouraged.
|
||||
|
||||
5.2 Datafiles
|
||||
^^^^^^^^^^^^^
|
||||
|
||||
If your test needs datafiles to work, these should be put into a subdirectory
|
||||
named 'datafiles' and installed into the 'testcases/data/$TCID' directory (to
|
||||
do that you have to add 'INSTALL_DIR := testcases/data/TCID' into the
|
||||
'datafiles/Makefile').
|
||||
|
||||
You can obtain path to datafiles via $TST_DATAROOT provided by test.sh
|
||||
'$TST_DATAROOT/...'
|
||||
or via C function 'tst_dataroot()' provided by libltp:
|
||||
|
||||
[source,c]
|
||||
-------------------------------------------------------------------------------
|
||||
const char *dataroot = tst_dataroot();
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Datafiles can also be accessed as '$LTPROOT/testcases/data/$TCID/...',
|
||||
but '$TST_DATAROOT' and 'tst_dataroot()' are preferred as these can be used
|
||||
when running testcases directly in git tree as well as from install
|
||||
location.
|
||||
|
||||
The path is constructed according to these rules:
|
||||
|
||||
1. if '$LTPROOT' is set, return '$LTPROOT/testcases/data/$TCID'
|
||||
2. else if 'tst_tmpdir()' was called return '$STARTWD/datafiles'
|
||||
(where '$STARTWD' is initial working directory as recorded by 'tst_tmpdir()')
|
||||
3. else return '$CWD/datafiles'
|
||||
|
||||
See 'testcases/commands/file/' for example.
|
||||
|
||||
5.3 Subexecutables
|
||||
^^^^^^^^^^^^^^^^^^
|
||||
|
||||
If your test needs to execute a binary, place it in the same directory as the
|
||||
testcase and name the file starting with '${test_binary_name}_'. Once the
|
||||
test is executed by the framework, the path to the directory with all LTP
|
||||
binaries is added to the '$PATH' and you can execute it just by its name.
|
||||
|
||||
TIP: If you need to execute such test from the LTP tree, you can add path to
|
||||
current directory to '$PATH' manually with: 'PATH="$PATH:$PWD" ./foo01'.
|
||||
|
||||
6 Test Contribution Checklist
|
||||
------------------------------
|
||||
|
||||
NOTE: See also
|
||||
https://github.com/linux-test-project/ltp/wiki/Maintainer-Patch-Review-Checklist[Maintainer Patch Review Checklist].
|
||||
|
||||
1. Test compiles and runs fine (check with `-i 10` too)
|
||||
2. `make check` does not emit any warnings for the test you are working on
|
||||
(hint: run it in the test's directory and/or use `make check-$TCID`)
|
||||
3. The runtest entries are in place
|
||||
4. Test binaries are added into corresponding '.gitignore' files
|
||||
5. Patches apply over the latest git
|
||||
|
||||
6.1 About .gitignore files
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
There are numerous '.gitignore' files in the LTP tree. Usually there is a
|
||||
'.gitignore' file per a group of tests. The reason for this setup is simple.
|
||||
It's easier to maintain a '.gitignore' file per directory with tests, rather
|
||||
than having single file in the project root directory. This way, we don't have
|
||||
to update all the gitignore files when moving directories, and they get deleted
|
||||
automatically when a directory with tests is removed.
|
||||
|
||||
7 Testing pre-release kernel features
|
||||
-------------------------------------
|
||||
|
||||
Tests for features not yet in a mainline kernel release are accepted. However
|
||||
they must only be added to the +staging+ runtest file. Once a feature is part
|
||||
of the stable kernel ABI the associated test must be moved out of staging.
|
||||
|
||||
This is primarily to help test kernel RCs by avoiding the need to download
|
||||
separate LTP patchsets.
|
||||
|
||||
8 LTP C And Shell Test API Comparison
|
||||
-------------------------------------
|
||||
|
||||
Comparison of
|
||||
https://github.com/linux-test-project/ltp/wiki/C-Test-API[C Test API] and
|
||||
https://github.com/linux-test-project/ltp/wiki/Shell-Test-API[Shell Test API].
|
||||
|
||||
[options="header"]
|
||||
|================================================================================
|
||||
| C API ('struct tst_test' members) | shell API ('$TST_*' environment variables)
|
||||
| '.all_filesystems' | 'TST_ALL_FILESYSTEMS'
|
||||
| '.bufs' | –
|
||||
| '.caps' | –
|
||||
| '.child_needs_reinit' | not applicable
|
||||
| '.cleanup' | 'TST_CLEANUP'
|
||||
| '.dev_extra_opts' | 'TST_DEV_EXTRA_OPTS'
|
||||
| '.dev_fs_opts' | 'TST_DEV_FS_OPTS'
|
||||
| '.dev_fs_type' | 'TST_FS_TYPE'
|
||||
| '.dev_min_size' | not applicable
|
||||
| '.format_device' | 'TST_FORMAT_DEVICE'
|
||||
| '.max_runtime' | –
|
||||
| '.min_cpus' | not applicable
|
||||
| '.min_kver' | 'TST_MIN_KVER'
|
||||
| '.min_mem_avail' | not applicable
|
||||
| '.mnt_flags' | 'TST_MNT_PARAMS'
|
||||
| '.min_swap_avail' | not applicable
|
||||
| '.mntpoint', '.mnt_data' | 'TST_MNTPOINT'
|
||||
| '.mount_device' | 'TST_MOUNT_DEVICE'
|
||||
| '.needs_cgroup_ctrls' | –
|
||||
| '.needs_checkpoints' | 'TST_NEEDS_CHECKPOINTS'
|
||||
| '.needs_cmds' | 'TST_NEEDS_CMDS'
|
||||
| '.needs_devfs' | –
|
||||
| '.needs_device' | 'TST_NEEDS_DEVICE'
|
||||
| '.needs_drivers' | 'TST_NEEDS_DRIVERS'
|
||||
| '.needs_kconfigs' | 'TST_NEEDS_KCONFIGS'
|
||||
| '.needs_overlay' |
|
||||
| '.needs_rofs' | –
|
||||
| '.needs_root' | 'TST_NEEDS_ROOT'
|
||||
| '.needs_tmpdir' | 'TST_NEEDS_TMPDIR'
|
||||
| '.options' | 'TST_PARSE_ARGS', 'TST_OPTS'
|
||||
| '.resource_files' | –
|
||||
| '.restore_wallclock' | not applicable
|
||||
| '.sample' | –
|
||||
| '.save_restore' | –
|
||||
| '.scall' | not applicable
|
||||
| '.setup' | 'TST_SETUP'
|
||||
| '.skip_filesystems' | 'TST_SKIP_FILESYSTEMS'
|
||||
| '.skip_in_compat' | –
|
||||
| '.skip_in_lockdown' | 'TST_SKIP_IN_LOCKDOWN'
|
||||
| '.skip_in_secureboot' | 'TST_SKIP_IN_SECUREBOOT'
|
||||
| '.supported_archs' | not applicable
|
||||
| '.tags' | –
|
||||
| '.taint_check' | –
|
||||
| '.tcnt' | 'TST_CNT'
|
||||
| '.tconf_msg' | not applicable
|
||||
| '.test', '.test_all' | 'TST_TESTFUNC'
|
||||
| '.test_variants' | –
|
||||
| '.timeout' | 'TST_TIMEOUT'
|
||||
| '.tst_hugepage' | not applicable
|
||||
| .format_device | 'TST_DEVICE'
|
||||
| not applicable | 'TST_NEEDS_KCONFIGS_IFS'
|
||||
| not applicable | 'TST_NEEDS_MODULE'
|
||||
| not applicable | 'TST_POS_ARGS'
|
||||
| not applicable | 'TST_USAGE'
|
||||
|================================================================================
|
||||
@@ -1,68 +0,0 @@
|
||||
LTP User Guidelines
|
||||
===================
|
||||
|
||||
For compiling, installing and running the tests see `README.md`.
|
||||
For running LTP network tests see `testcases/network/README.md`.
|
||||
|
||||
1. Library environment variables
|
||||
--------------------------------
|
||||
|
||||
|==============================================================================
|
||||
| 'KCONFIG_PATH' | The path to the kernel config file, (if not set, it tries
|
||||
the usual paths '/boot/config-RELEASE' or '/proc/config.gz').
|
||||
| 'KCONFIG_SKIP_CHECK' | Skip kernel config check if variable set (not set by default).
|
||||
| 'LTPROOT' | Prefix for installed LTP. **Should be always set**
|
||||
as some tests need it for path to test data files
|
||||
('LTP_DATAROOT'). LTP is by default installed into '/opt/ltp'.
|
||||
| 'LTP_COLORIZE_OUTPUT' | By default LTP colorizes it's output unless it's redirected
|
||||
to a pipe or file. Force colorized output behaviour:
|
||||
'y' or '1': always colorize, 'n' or '0': never colorize.
|
||||
| 'LTP_DEV' | Path to the block device to be used
|
||||
(C: '.needs_device = 1', shell: 'TST_NEEDS_DEVICE=1').
|
||||
| 'LTP_SINGLE_FS_TYPE' | Testing only - specifies filesystem instead all
|
||||
supported (for tests with '.all_filesystems').
|
||||
| 'LTP_DEV_FS_TYPE' | Filesystem used for testing (default: 'ext2').
|
||||
| 'LTP_TIMEOUT_MUL' | Multiplies timeout, must be number >= 0.1 (> 1 is useful for
|
||||
slow machines to avoid unexpected timeout).
|
||||
Variable is also used in shell tests, but ceiled to int.
|
||||
| 'LTP_RUNTIME_MUL' | Multiplies maximal test iteration runtime. Tests
|
||||
that run for more than a second or two are capped on
|
||||
runtime. You can scale the default runtime both up
|
||||
and down with this multiplier. NOTE: Not yet implemented
|
||||
in shell API.
|
||||
| 'LTP_VIRT_OVERRIDE' | Overrides virtual machine detection in the test
|
||||
library. Setting it to empty string tell the library
|
||||
that system is not a virtual machine. Other possible
|
||||
values are 'kvm', 'xen', 'zvm' and 'microsoft' that
|
||||
describe different types supervisors.
|
||||
| 'PATH' | It's required to addjust path:
|
||||
`PATH="$PATH:$LTPROOT/testcases/bin"`
|
||||
| 'TMPDIR' | Base directory for template directory (C: '.needs_tmpdir = 1'
|
||||
and others, which imply it, shell: 'TST_NEEDS_TMPDIR=1').
|
||||
Must be an absolute path (default: '/tmp').
|
||||
| 'TST_NO_CLEANUP' | Disable running test cleanup (defined in 'TST_CLEANUP').
|
||||
|==============================================================================
|
||||
|
||||
|
||||
2. Test execution time and timeout
|
||||
----------------------------------
|
||||
|
||||
The limit on how long a test can run does compose of two parts max_runtime and
|
||||
timeout. The limit does apply to a single test variant, that means for example
|
||||
that tests that run for all available filesystems will apply this limit for a
|
||||
single filesystem only.
|
||||
|
||||
The max_runtime is a cap on how long the run() function can take, for most
|
||||
testcases this part is set to zero. For tests that do run for more than a
|
||||
second or two the max_runtime has to be defined and the run() function has to
|
||||
check actively how much runtime is left.
|
||||
|
||||
Test runtime can be scaled up and down with 'LTP_RUNTIME_MUL' environment
|
||||
variable or set on a commandline by the '-I' parameter. Hoewever be vary that
|
||||
setting the runtime too low will cause long running tests to exit prematurely
|
||||
possibly before the have a chance actually test anyting.
|
||||
|
||||
The timeout part is a limit for the test setup and cleanup and also safety
|
||||
margin for the runtime accounting. It's currently set to 30 seconds but may
|
||||
change later. If your target machine is too slow it can be scaled up with the
|
||||
'LTP_TIMEOUT_MUL' environment variable.
|
||||
Vendored
+9
@@ -0,0 +1,9 @@
|
||||
/* set multiline tables cells */
|
||||
.wy-table-responsive table td {
|
||||
white-space: normal;
|
||||
}
|
||||
|
||||
/* remove margin for multiline cells */
|
||||
.rst-content table td div.line-block {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
+542
@@ -0,0 +1,542 @@
|
||||
# Configuration file for the Sphinx documentation builder.
|
||||
#
|
||||
# For the full list of built-in configuration values, see the documentation:
|
||||
# https://www.sphinx-doc.org/en/master/usage/configuration.html
|
||||
|
||||
import os
|
||||
import re
|
||||
import json
|
||||
import socket
|
||||
import urllib.request
|
||||
import sphinx
|
||||
|
||||
# -- Project information -----------------------------------------------------
|
||||
# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information
|
||||
|
||||
project = 'Linux Test Project'
|
||||
copyright = '2024, Linux Test Project'
|
||||
author = 'Linux Test Project'
|
||||
release = '1.0'
|
||||
ltp_repo = 'https://github.com/linux-test-project/ltp'
|
||||
ltp_repo_base_url = f"{ltp_repo}/tree/master"
|
||||
|
||||
# -- General configuration ---------------------------------------------------
|
||||
# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration
|
||||
|
||||
extensions = [
|
||||
'linuxdoc.rstKernelDoc',
|
||||
'sphinxcontrib.spelling',
|
||||
'sphinx.ext.autosectionlabel',
|
||||
'sphinx.ext.extlinks',
|
||||
]
|
||||
|
||||
exclude_patterns = ["html*", '_static*', '.venv*']
|
||||
extlinks = {
|
||||
'repo': (f'{ltp_repo}/%s', '%s'),
|
||||
'master': (f'{ltp_repo}/blob/master/%s', '%s'),
|
||||
'git_man': ('https://git-scm.com/docs/git-%s', 'git %s'),
|
||||
'man2': ('https://man7.org/linux/man-pages/man2/%s.2.html', '%s(2)'),
|
||||
# TODO: allow 2nd parameter to show page description instead of plain URL
|
||||
'kernel_doc': ('https://docs.kernel.org/%s.html', 'https://docs.kernel.org/%s.html'),
|
||||
'kernel_tree': ('https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/%s', '%s'),
|
||||
}
|
||||
|
||||
spelling_lang = "en_US"
|
||||
spelling_warning = True
|
||||
spelling_exclude_patterns = ['users/stats.rst']
|
||||
spelling_word_list_filename = "spelling_wordlist"
|
||||
|
||||
# -- Options for HTML output -------------------------------------------------
|
||||
# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output
|
||||
|
||||
html_theme = 'sphinx_rtd_theme'
|
||||
html_static_path = ['_static']
|
||||
|
||||
|
||||
def generate_syscalls_stats(_):
|
||||
"""
|
||||
Generate statistics for syscalls. We fetch the syscalls list from the kernel
|
||||
sources, then we compare it with testcases/kernel/syscalls folder and
|
||||
generate a file that is included in the statistics documentation section.
|
||||
"""
|
||||
output = '_static/syscalls.rst'
|
||||
|
||||
# sometimes checking testcases/kernel/syscalls file names are not enough,
|
||||
# because in some cases (i.e. io_ring) syscalls are tested, but they are
|
||||
# part of a more complex scenario. In the following list, we define syscalls
|
||||
# which we know they are 100% tested already.
|
||||
ltp_syscalls_path = "testcases/kernel/syscalls"
|
||||
white_list = {
|
||||
'bpf': f'{ltp_syscalls_path}/bpf',
|
||||
'epoll_pwait2': f'{ltp_syscalls_path}/epoll_pwait',
|
||||
'fadvise64': f'{ltp_syscalls_path}/fadvise',
|
||||
'fanotify_init': f'{ltp_syscalls_path}/fanotify',
|
||||
'fanotify_mark': f'{ltp_syscalls_path}/fanotify',
|
||||
'file_getattr': f'{ltp_syscalls_path}/file_attr',
|
||||
'file_setattr': f'{ltp_syscalls_path}/file_attr',
|
||||
'futex': f'{ltp_syscalls_path}/futex',
|
||||
'getdents64': f'{ltp_syscalls_path}/gettdents',
|
||||
'inotify_add_watch': f'{ltp_syscalls_path}/inotify',
|
||||
'inotify_init': f'{ltp_syscalls_path}/inotify',
|
||||
'inotify_rm_watch': f'{ltp_syscalls_path}/inotify',
|
||||
'io_uring_enter': f'{ltp_syscalls_path}/io_uring',
|
||||
'io_uring_register': f'{ltp_syscalls_path}/io_uring',
|
||||
'io_uring_setup': f'{ltp_syscalls_path}/io_uring',
|
||||
'landlock_add_rule': f'{ltp_syscalls_path}/landlock',
|
||||
'landlock_create_ruleset': f'{ltp_syscalls_path}/landlock',
|
||||
'landlock_restrict_self': f'{ltp_syscalls_path}/landlock',
|
||||
'lsetxattr': f'{ltp_syscalls_path}/lgetxattr',
|
||||
'newfstatat': f'{ltp_syscalls_path}/fstatat',
|
||||
'pkey_alloc': f'{ltp_syscalls_path}/pkeys',
|
||||
'pkey_free': f'{ltp_syscalls_path}/pkeys',
|
||||
'pkey_mprotect': f'{ltp_syscalls_path}/pkeys',
|
||||
'prlimit64': f'{ltp_syscalls_path}/getrlimit',
|
||||
'pread64': f'{ltp_syscalls_path}/pread',
|
||||
'pselect6': f'{ltp_syscalls_path}/pselect',
|
||||
'pwrite64': f'{ltp_syscalls_path}/pwrite',
|
||||
'quotactl_fd': f'{ltp_syscalls_path}/quotactl',
|
||||
'rt_sigpending': f'{ltp_syscalls_path}/sigpending',
|
||||
'semtimedop': f'{ltp_syscalls_path}/ipc/semop',
|
||||
'sethostname': f'{ltp_syscalls_path}/sethostname'
|
||||
}
|
||||
|
||||
# populate with not implemented, reserved, unmaintained syscalls defined
|
||||
# inside the syscalls file
|
||||
black_list = [
|
||||
'_newselect',
|
||||
'_sysctl',
|
||||
'afs_syscall',
|
||||
'cachectl',
|
||||
'create_module',
|
||||
'get_kernel_syms',
|
||||
'getmsg',
|
||||
'getpmsg',
|
||||
'mq_getsetattr',
|
||||
'nfsservctl',
|
||||
'putmsg',
|
||||
'putpmsg',
|
||||
'query_module',
|
||||
'reserved177',
|
||||
'reserved193',
|
||||
'restart_syscall',
|
||||
'rseq',
|
||||
'sysmips',
|
||||
'vserver',
|
||||
]
|
||||
|
||||
# fetch syscalls file
|
||||
syscalls_url = "https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/plain/arch/mips/kernel/syscalls"
|
||||
error = False
|
||||
try:
|
||||
socket.setdefaulttimeout(3)
|
||||
|
||||
# kernel.org doesn't always allow to download syscalls file, so we need
|
||||
# to emulate a different client in order to download it. Browser
|
||||
# emulation might fail due to captcha request and for this reason we
|
||||
# use the 'curl' command instead
|
||||
req = urllib.request.Request(
|
||||
f"{syscalls_url}/syscall_n64.tbl",
|
||||
headers={'User-Agent': 'curl/8.6.0'})
|
||||
|
||||
with urllib.request.urlopen(req) as response:
|
||||
with open("syscalls.tbl", 'wb') as out_file:
|
||||
out_file.write(response.read())
|
||||
except urllib.error.URLError as err:
|
||||
error = True
|
||||
logger = sphinx.util.logging.getLogger(__name__)
|
||||
msg = f"Can't download syscall_n64.tbl from kernel sources ({err})"
|
||||
logger.warning(msg)
|
||||
|
||||
with open(output, 'w+', encoding='utf-8') as stats:
|
||||
stats.write(f".. warning::\n\n {msg}")
|
||||
|
||||
if error:
|
||||
return
|
||||
|
||||
text = [
|
||||
'Syscalls\n',
|
||||
'--------\n\n',
|
||||
]
|
||||
|
||||
# collect all available kernel syscalls
|
||||
regexp = re.compile(r'\d+\s+n64\s+(?P<syscall>\w+)\s+\w+')
|
||||
ker_syscalls = []
|
||||
with open("syscalls.tbl", 'r', encoding='utf-8') as data:
|
||||
for line in data:
|
||||
match = regexp.search(line)
|
||||
if not match:
|
||||
continue
|
||||
|
||||
ker_syscalls.append(match.group('syscall'))
|
||||
|
||||
# collect all LTP tested syscalls
|
||||
name_patterns = [
|
||||
re.compile(r'(?P<name>[a-zA-Z_]+[^_])\d{2}\.c'),
|
||||
re.compile(r'(?P<name>[a-zA-Z_]+[1-9])_\d{2}\.c'),
|
||||
]
|
||||
ltp_syscalls = {}
|
||||
for dirpath, _, files in os.walk(f'../{ltp_syscalls_path}'):
|
||||
for myfile in files:
|
||||
match = None
|
||||
for pattern in name_patterns:
|
||||
match = pattern.search(myfile)
|
||||
if match:
|
||||
break
|
||||
|
||||
if not match:
|
||||
continue
|
||||
|
||||
# we need to use relative path from the project root
|
||||
path = dirpath.replace('../', '')
|
||||
name = match.group('name')
|
||||
|
||||
ltp_syscalls[name] = f'{ltp_repo_base_url}/{path}'
|
||||
|
||||
# compare kernel syscalls with LTP tested syscalls
|
||||
syscalls = {}
|
||||
for kersc in ker_syscalls:
|
||||
if kersc in black_list:
|
||||
continue
|
||||
|
||||
if kersc not in syscalls:
|
||||
if kersc in white_list:
|
||||
syscalls[kersc] = f'{ltp_repo_base_url}/{white_list[kersc]}'
|
||||
continue
|
||||
|
||||
syscalls[kersc] = None
|
||||
|
||||
for ltpsc, ltpsp in ltp_syscalls.items():
|
||||
if ltpsc == kersc:
|
||||
syscalls[kersc] = ltpsp
|
||||
|
||||
# generate the statistics file
|
||||
tested_syscalls = [key for key, val in syscalls.items() if val is not None]
|
||||
text.append('syscalls which are tested under '
|
||||
':master:`testcases/kernel/syscalls`:\n\n')
|
||||
text.append(f'* kernel syscalls: {len(ker_syscalls)}\n')
|
||||
text.append(f'* tested syscalls: {len(tested_syscalls)}\n\n')
|
||||
|
||||
# create tested/untested syscalls table
|
||||
index_tested = 0
|
||||
table_tested = [
|
||||
'Tested syscalls\n',
|
||||
'~~~~~~~~~~~~~~~\n\n',
|
||||
'.. list-table::\n',
|
||||
' :header-rows: 0\n\n',
|
||||
]
|
||||
|
||||
index_untest = 0
|
||||
table_untest = [
|
||||
'Untested syscalls\n',
|
||||
'~~~~~~~~~~~~~~~~~\n\n',
|
||||
'.. list-table::\n',
|
||||
' :header-rows: 0\n\n',
|
||||
]
|
||||
|
||||
max_columns = 3
|
||||
|
||||
for sysname, path in syscalls.items():
|
||||
if path is not None:
|
||||
if (index_tested % max_columns) == 0:
|
||||
table_tested.append(f' * - `{sysname} <{path}>`_\n')
|
||||
else:
|
||||
table_tested.append(f' - `{sysname} <{path}>`_\n')
|
||||
|
||||
index_tested += 1
|
||||
else:
|
||||
if (index_untest % max_columns) == 0:
|
||||
table_untest.append(f' * - {sysname}\n')
|
||||
else:
|
||||
table_untest.append(f' - {sysname}\n')
|
||||
|
||||
index_untest += 1
|
||||
|
||||
left = index_tested % max_columns
|
||||
if left > 0:
|
||||
for _ in range(0, max_columns - left):
|
||||
table_tested.append(' -\n')
|
||||
|
||||
left = index_untest % max_columns
|
||||
if left > 0:
|
||||
for _ in range(0, max_columns - left):
|
||||
table_untest.append(' -\n')
|
||||
|
||||
text.extend(table_tested)
|
||||
text.append('\n')
|
||||
text.extend(table_untest)
|
||||
|
||||
# write the file
|
||||
with open(output, 'w+', encoding='utf-8') as stats:
|
||||
stats.writelines(text)
|
||||
|
||||
|
||||
def _generate_tags_table(tags):
|
||||
"""
|
||||
Generate the tags table from tags hash.
|
||||
"""
|
||||
supported_url_ref = {
|
||||
"linux-git": "https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=",
|
||||
"linux-stable-git": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=",
|
||||
"glibc-git": "https://sourceware.org/git/?p=glibc.git;a=commit;h=",
|
||||
"musl-git": "https://git.musl-libc.org/cgit/musl/commit/src/linux/clone.c?id=",
|
||||
"CVE": "https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-",
|
||||
}
|
||||
|
||||
table = [
|
||||
'.. list-table::',
|
||||
' :header-rows: 1',
|
||||
'',
|
||||
' * - Tag',
|
||||
' - Info',
|
||||
]
|
||||
|
||||
for tag in tags:
|
||||
tag_key = tag[0]
|
||||
tag_val = tag[1]
|
||||
|
||||
tag_url = supported_url_ref.get(tag_key, None)
|
||||
if tag_url:
|
||||
tag_val = f'`{tag_val} <{tag_url}{tag_val}>`_'
|
||||
|
||||
table.extend([
|
||||
f' * - :c:struct:`{tag_key} <tst_tag>`',
|
||||
f' - {tag_val}',
|
||||
])
|
||||
|
||||
return table
|
||||
|
||||
|
||||
def _generate_options_table(options):
|
||||
"""
|
||||
Generate the options table from the options hash.
|
||||
"""
|
||||
table = [
|
||||
'.. list-table::',
|
||||
' :header-rows: 1',
|
||||
'',
|
||||
' * - Option',
|
||||
' - Description',
|
||||
]
|
||||
|
||||
for opt in options:
|
||||
if not isinstance(opt, list):
|
||||
table.clear()
|
||||
break
|
||||
|
||||
key = opt[0]
|
||||
val = opt[2]
|
||||
|
||||
if key.endswith(':'):
|
||||
key = key[:-1] if key.endswith(':') else key
|
||||
|
||||
key = f'-{key}'
|
||||
|
||||
table.extend([
|
||||
f' * - {key}',
|
||||
f' - {val}',
|
||||
])
|
||||
|
||||
return table
|
||||
|
||||
|
||||
def _generate_table_cell(key, values):
|
||||
"""
|
||||
Generate a cell which can be multiline if value is a list.
|
||||
"""
|
||||
cell = []
|
||||
key = f' :c:struct:`{key} <tst_test>`'
|
||||
|
||||
if len(values) > 1:
|
||||
cell.extend([
|
||||
f' * - {key}',
|
||||
f' - | {values[0]}',
|
||||
])
|
||||
|
||||
for item in values[1:]:
|
||||
cell.append(f' | {item}')
|
||||
else:
|
||||
cell.extend([
|
||||
f' * - {key}',
|
||||
f' - {values[0]}',
|
||||
])
|
||||
|
||||
return cell
|
||||
|
||||
|
||||
def _generate_setup_table(keys):
|
||||
"""
|
||||
Generate the table with test setup configuration.
|
||||
"""
|
||||
exclude = [
|
||||
# following keys are already handled
|
||||
'options',
|
||||
'runtime',
|
||||
'timeout',
|
||||
'fname',
|
||||
'doc',
|
||||
# following keys don't need to be shown
|
||||
'child_needs_reinit',
|
||||
'needs_checkpoints',
|
||||
'forks_child',
|
||||
'tags',
|
||||
]
|
||||
my_keys = {k: v for k, v in keys.items() if k not in exclude}
|
||||
if len(my_keys) == 0:
|
||||
return []
|
||||
|
||||
table = [
|
||||
'.. list-table::',
|
||||
' :header-rows: 1',
|
||||
'',
|
||||
' * - Key',
|
||||
' - Value',
|
||||
]
|
||||
|
||||
values = []
|
||||
|
||||
for key, value in my_keys.items():
|
||||
if key in exclude:
|
||||
continue
|
||||
|
||||
values.clear()
|
||||
|
||||
if key == 'ulimit':
|
||||
for item in value:
|
||||
values.append(f'{item[0]} : {item[1]}')
|
||||
elif key == 'hugepages':
|
||||
if len(value) == 1:
|
||||
values.append(f'{value[0]}')
|
||||
else:
|
||||
values.append(f'{value[0]}, {value[1]}')
|
||||
elif key == 'filesystems':
|
||||
for params in value:
|
||||
for pkey, pval in params.items():
|
||||
if pkey == "type":
|
||||
values.append(f"- {pval}")
|
||||
else:
|
||||
values.append(f" {pkey}: {pval}")
|
||||
elif key == "save_restore":
|
||||
for item in value:
|
||||
values.append(item[0])
|
||||
else:
|
||||
if isinstance(value, list):
|
||||
values.extend(value)
|
||||
else:
|
||||
values.append(value)
|
||||
|
||||
if values:
|
||||
table.extend(_generate_table_cell(key, values))
|
||||
|
||||
return table
|
||||
|
||||
|
||||
def generate_test_catalog(_):
|
||||
"""
|
||||
Generate the test catalog from ltp.json metadata file.
|
||||
"""
|
||||
output = '_static/tests.rst'
|
||||
metadata_file = '../metadata/ltp.json'
|
||||
text = [
|
||||
'.. warning::',
|
||||
' The following catalog has been generated using LTP metadata',
|
||||
' which is including only tests using the new :ref:`LTP C API`.',
|
||||
''
|
||||
]
|
||||
|
||||
metadata = None
|
||||
with open(metadata_file, 'r', encoding='utf-8') as data:
|
||||
metadata = json.load(data)
|
||||
|
||||
timeout_def = metadata['defaults']['timeout']
|
||||
regexp = re.compile(r'^\[([A-Za-z][\w\W]+)\]')
|
||||
|
||||
for test_name, conf in sorted(metadata['tests'].items()):
|
||||
text.extend([
|
||||
f'{test_name}',
|
||||
len(test_name) * '-'
|
||||
])
|
||||
|
||||
# source url location
|
||||
test_fname = conf.get('fname', None)
|
||||
if test_fname:
|
||||
text.extend([
|
||||
'',
|
||||
f"`source <{ltp_repo_base_url}/{test_fname}>`__",
|
||||
''
|
||||
])
|
||||
|
||||
# test description
|
||||
desc = conf.get('doc', None)
|
||||
if desc:
|
||||
desc_text = []
|
||||
for line in desc:
|
||||
line = regexp.sub(r'**\1**', line)
|
||||
desc_text.append(line)
|
||||
|
||||
text.extend([
|
||||
'\n'.join(desc_text),
|
||||
])
|
||||
|
||||
# timeout information
|
||||
timeout = conf.get('timeout', None)
|
||||
if timeout:
|
||||
text.extend([
|
||||
'',
|
||||
f'Test timeout is {timeout} seconds.',
|
||||
])
|
||||
else:
|
||||
text.extend([
|
||||
'',
|
||||
f'Test timeout defaults is {timeout_def} seconds.',
|
||||
])
|
||||
|
||||
# runtime information
|
||||
runtime = conf.get('runtime', None)
|
||||
if runtime:
|
||||
text.extend([
|
||||
f'Maximum runtime is {runtime} seconds.',
|
||||
''
|
||||
])
|
||||
else:
|
||||
text.append('')
|
||||
|
||||
# options information
|
||||
opts = conf.get('options', None)
|
||||
if opts:
|
||||
text.append('')
|
||||
text.extend(_generate_options_table(opts))
|
||||
text.append('')
|
||||
|
||||
# tags information
|
||||
tags = conf.get('tags', None)
|
||||
if tags:
|
||||
text.append('')
|
||||
text.extend(_generate_tags_table(tags))
|
||||
text.append('')
|
||||
|
||||
# parse struct tst_test content
|
||||
text.append('')
|
||||
text.extend(_generate_setup_table(conf))
|
||||
text.append('')
|
||||
|
||||
# small separator between tests
|
||||
text.extend([
|
||||
'',
|
||||
'.. raw:: html',
|
||||
'',
|
||||
' <hr>',
|
||||
'',
|
||||
])
|
||||
|
||||
with open(output, 'w+', encoding='utf-8') as new_tests:
|
||||
new_tests.write('\n'.join(text))
|
||||
|
||||
|
||||
def setup(app):
|
||||
"""
|
||||
Setup the current documentation, using self generated data and graphics
|
||||
customizations.
|
||||
"""
|
||||
app.add_css_file('custom.css')
|
||||
app.connect('builder-inited', generate_syscalls_stats)
|
||||
app.connect('builder-inited', generate_test_catalog)
|
||||
@@ -0,0 +1,56 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0-or-later
|
||||
.. Copyright (c) Linux Test Project, 2024
|
||||
|
||||
.. Include headers in this file with:
|
||||
.. .. kernel-doc:: ../../include/tst_test.h
|
||||
|
||||
LTP C API
|
||||
=========
|
||||
|
||||
Core LTP API
|
||||
------------
|
||||
.. kernel-doc:: ../../include/tst_res_flags.h
|
||||
.. kernel-doc:: ../../include/tst_test.h
|
||||
|
||||
Test macros
|
||||
-----------
|
||||
.. kernel-doc:: ../../include/tst_test_macros.h
|
||||
|
||||
Capabilities
|
||||
------------
|
||||
.. kernel-doc:: ../../include/tst_capability.h
|
||||
|
||||
Checkpoints
|
||||
-----------
|
||||
|
||||
.. kernel-doc:: ../../include/tst_checkpoint.h
|
||||
|
||||
Crypto
|
||||
------
|
||||
.. kernel-doc:: ../../include/tst_crypto.h
|
||||
.. kernel-doc:: ../../include/tst_af_alg.h
|
||||
|
||||
Guarded buffers
|
||||
---------------
|
||||
.. kernel-doc:: ../../include/tst_buffers.h
|
||||
|
||||
Kernel
|
||||
------
|
||||
.. kernel-doc:: ../../include/tst_kernel.h
|
||||
|
||||
NUMA
|
||||
----
|
||||
.. kernel-doc:: ../../include/tst_numa.h
|
||||
|
||||
Option parsing
|
||||
--------------
|
||||
|
||||
.. kernel-doc:: ../../include/tst_parse.h
|
||||
|
||||
Temporary directory
|
||||
-------------------
|
||||
.. kernel-doc:: ../../include/tst_tmpdir.h
|
||||
|
||||
LTP libraries
|
||||
-------------
|
||||
.. kernel-doc:: ../../include/libswap.h
|
||||
@@ -0,0 +1,485 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
.. Include headers in this file with:
|
||||
.. .. kernel-doc:: ../../include/tst_test.h
|
||||
|
||||
Developing using KVM API
|
||||
========================
|
||||
|
||||
Testing KVM is more complex than other Linux features. Some KVM bugs allow
|
||||
userspace code running inside the virtual machine to bypass (emulated) hardware
|
||||
access restrictions and elevate its privileges inside the guest operating
|
||||
system. The worst types of KVM bugs may even allow the guest code to crash or
|
||||
compromise the physical host. KVM tests therefore need to be split into two
|
||||
components – a KVM controller program running on the physical host and a guest
|
||||
payload program running inside the VM. The cooperation of these two components
|
||||
allows testing even of bugs that somehow cross the virtualization boundary.
|
||||
|
||||
Basic KVM Test Structure
|
||||
------------------------
|
||||
|
||||
KVM tests are simple C source files containing both the KVM controller code
|
||||
and the guest payload code separated by ``#ifdef COMPILE_PAYLOAD`` preprocessor
|
||||
condition. The file will be compiled twice: once to compile the payload part,
|
||||
and once to compile the KVM controller part and embed the payload binary inside.
|
||||
The result is a single self-contained binary that will execute the embedded
|
||||
payload inside a KVM virtual machine and print results in the same format as
|
||||
a normal LTP test.
|
||||
|
||||
A KVM test source should start with ``#include "kvm_test.h"`` instead of the
|
||||
usual ``tst_test.h``. The ``kvm_test.h`` header file will include the other basic
|
||||
headers appropriate for the current compilation pass. Everything else in the
|
||||
source file should be enclosed in ``#ifdef COMPILE_PAYLOAD ... #else ... #endif``
|
||||
condition, including any other header file includes. Note that the standard
|
||||
LTP headers are not available in the payload compilation pass; only the KVM
|
||||
guest library headers can be included.
|
||||
|
||||
.. _example-kvm-test:
|
||||
|
||||
.. rubric:: Example KVM Test
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
#include "kvm_test.h"
|
||||
|
||||
#ifdef COMPILE_PAYLOAD
|
||||
|
||||
/* Guest payload code */
|
||||
|
||||
void main(void)
|
||||
{
|
||||
tst_res(TPASS, "Hello, world!");
|
||||
}
|
||||
|
||||
#else /* COMPILE_PAYLOAD */
|
||||
|
||||
/* KVM controller code */
|
||||
|
||||
static struct tst_test test = {
|
||||
.test_all = tst_kvm_run,
|
||||
.setup = tst_kvm_setup,
|
||||
.cleanup = tst_kvm_cleanup,
|
||||
};
|
||||
|
||||
#endif /* COMPILE_PAYLOAD */
|
||||
|
||||
The KVM controller code is a normal LTP test and needs to define an instance
|
||||
of ``struct tst_test`` with metadata and the usual setup, cleanup, and test
|
||||
functions. Basic implementation of all three functions is provided by the KVM
|
||||
host library.
|
||||
|
||||
On the other hand, the payload is essentially a tiny kernel that will run
|
||||
on bare virtual hardware. It cannot access any files, Linux syscalls, standard
|
||||
library functions, etc., except for the small subset provided by the KVM guest
|
||||
library. The payload code must define a ``void main(void)`` function which will
|
||||
be the VM entry point of the test.
|
||||
|
||||
KVM Host Library
|
||||
----------------
|
||||
|
||||
The KVM host library provides helper functions for creating and running
|
||||
a minimal KVM virtual machine.
|
||||
|
||||
Data Structures
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
struct tst_kvm_instance {
|
||||
int vm_fd, vcpu_fd;
|
||||
struct kvm_run *vcpu_info;
|
||||
size_t vcpu_info_size;
|
||||
struct kvm_userspace_memory_region ram[MAX_KVM_MEMSLOTS];
|
||||
struct tst_kvm_result *result;
|
||||
};
|
||||
|
||||
``struct tst_kvm_instance`` holds the file descriptors and memory buffers
|
||||
of a single KVM virtual machine:
|
||||
|
||||
* ``int vm_fd`` is the main VM file descriptor created by ``ioctl(KVM_CREATE_VM)``
|
||||
* ``int vcpu_fd`` is the virtual CPU file descriptor created by
|
||||
``ioctl(KVM_CREATE_VCPU)``
|
||||
* ``struct kvm_run *vcpu_info`` is the VCPU state structure created by
|
||||
``mmap(vcpu_fd)``
|
||||
* ``size_t vcpu_info_size`` is the size of ``vcpu_info`` buffer
|
||||
* ``struct kvm_userspace_memory_region ram[MAX_KVM_MEMSLOTS]`` is the list
|
||||
of memory slots defined in this VM. Unused memory slots have zero
|
||||
in the ``userspace_addr`` field.
|
||||
* ``struct tst_kvm_result *result`` is a buffer for passing test result data
|
||||
from the VM to the controller program, mainly ``tst_res()``/``tst_brk()`` flags
|
||||
and messages.
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
struct tst_kvm_result {
|
||||
int32_t result;
|
||||
int32_t lineno;
|
||||
uint64_t file_addr;
|
||||
char message[0];
|
||||
};
|
||||
|
||||
``struct tst_kvm_result`` is used to pass test results and synchronization data
|
||||
between the KVM guest and the controller program. Most often, it is used
|
||||
to pass ``tst_res()`` and ``tst_brk()`` messages from the VM, but special values
|
||||
can also be used to send control flow requests both ways.
|
||||
|
||||
* ``int32_t result`` is the message type, either one of the ``TPASS``, ``TFAIL``,
|
||||
``TWARN``, ``TBROK``, ``TINFO`` flags or a special control flow value. Errno flags
|
||||
are not supported.
|
||||
* ``int32_t lineno`` is the line number for ``tst_res()``/``tst_brk()`` messages.
|
||||
* ``uint64_t file_addr`` is the VM address of the filename string for
|
||||
``tst_res()``/``tst_brk()`` messages.
|
||||
* ``char message[0]`` is the buffer for arbitrary message data, most often used
|
||||
to pass ``tst_res()``/``tst_brk()`` message strings.
|
||||
|
||||
Working with Virtual Machines
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The KVM host library provides default implementation of the setup, cleanup
|
||||
and test functions for ``struct tst_test`` in cases where you do not need
|
||||
to customize the VM configuration. You can either assign these functions
|
||||
to the ``struct tst_test`` instance directly or call them from your own function
|
||||
that does some additional steps. All three functions must be used together.
|
||||
|
||||
* ``void tst_kvm_setup(void)``
|
||||
* ``void tst_kvm_run(void)``
|
||||
* ``void tst_kvm_cleanup(void)``
|
||||
|
||||
.. note:: ``tst_kvm_run()`` calls ``tst_free_all()``. Calling it will free all
|
||||
previously allocated guarded buffers.
|
||||
|
||||
* ``void tst_kvm_validate_result(int value)`` – Validates whether the value
|
||||
returned in ``struct tst_kvm_result.result`` can be safely passed
|
||||
to ``tst_res()`` or ``tst_brk()``. If the value is not valid, the controller
|
||||
program will be terminated with an error.
|
||||
|
||||
* ``uint64_t tst_kvm_get_phys_address(const struct tst_kvm_instance *inst, uint64_t addr)`` –
|
||||
Converts pointer value (virtual address) from KVM virtual
|
||||
machine ``inst`` to the corresponding physical address. Returns 0 if
|
||||
the virtual address is not mapped to any physical address. If virtual memory
|
||||
mapping is not enabled in the VM or not available on the architecture at all, this
|
||||
function simply returns ``addr`` as is.
|
||||
|
||||
* ``int tst_kvm_find_phys_memslot(const struct tst_kvm_instance *inst, uint64_t paddr)`` –
|
||||
Returns index of the memory slot in KVM virtual machine
|
||||
``inst`` which contains the physical address ``paddr``. If the address is not
|
||||
backed by a memory buffer, returns -1.
|
||||
|
||||
* ``int tst_kvm_find_memslot(const struct tst_kvm_instance *inst, uint64_t addr)`` –
|
||||
Returns index of the memory slot in KVM virtual machine
|
||||
``inst`` which contains the virtual address ``addr``. If the virtual address
|
||||
is not mapped to a valid physical address backed by a memory buffer,
|
||||
returns -1.
|
||||
|
||||
* ``void *tst_kvm_get_memptr(const struct tst_kvm_instance *inst, uint64_t addr)`` –
|
||||
Converts pointer value (virtual address) from KVM virtual
|
||||
machine ``inst`` to host-side pointer.
|
||||
|
||||
* ``void *tst_kvm_alloc_memory(struct tst_kvm_instance *inst, unsigned int slot, uint64_t baseaddr, size_t size, unsigned int flags)`` –
|
||||
Allocates a guarded buffer of given ``size`` in bytes and installs it into specified memory ``slot``
|
||||
of the KVM virtual machine ``inst`` at base address ``baseaddr``. The buffer
|
||||
will be automatically page aligned at both ends. See the kernel
|
||||
documentation of ``KVM_SET_USER_MEMORY_REGION`` ioctl for a list of valid
|
||||
``flags``. Returns pointer to page-aligned beginning of the allocated buffer.
|
||||
The actual requested ``baseaddr`` will be located at
|
||||
``ret + baseaddr % pagesize``.
|
||||
|
||||
* ``struct kvm_cpuid2 *tst_kvm_get_cpuid(int sysfd)`` – Gets a list of supported
|
||||
virtual CPU features returned by ``ioctl(KVM_GET_SUPPORTED_CPUID)``.
|
||||
The argument must be an open file descriptor returned by ``open("/dev/kvm")``.
|
||||
|
||||
* ``void tst_kvm_create_instance(struct tst_kvm_instance *inst, size_t ram_size)`` –
|
||||
Creates and fully initializes a new KVM virtual machine
|
||||
with at least ``ram_size`` bytes of memory. The VM instance info will be
|
||||
stored in ``inst``.
|
||||
|
||||
* ``int tst_kvm_run_instance(struct tst_kvm_instance *inst, int exp_errno)`` –
|
||||
Executes the program installed in KVM virtual machine ``inst``. Any result
|
||||
messages returned by the VM will be automatically printed to the controller
|
||||
program output. Returns zero. If ``exp_errno`` is non-zero, the VM execution
|
||||
syscall is allowed to fail with the ``exp_errno`` error code and
|
||||
``tst_kvm_run_instance()`` will return -1 instead of terminating the test.
|
||||
|
||||
* ``void tst_kvm_destroy_instance(struct tst_kvm_instance *inst)`` – Deletes
|
||||
the KVM virtual machine ``inst``. Note that the guarded buffers assigned
|
||||
to the VM by ``tst_kvm_create_instance()`` or ``tst_kvm_alloc_memory()`` will
|
||||
not be freed.
|
||||
|
||||
The KVM host library does not provide any way to reset a VM instance back
|
||||
to its initial state. Running multiple iterations of the test requires destroying
|
||||
the old VM instance and creating a new one. Otherwise, the VM will exit
|
||||
without reporting any results on the second iteration, and the test will fail.
|
||||
The ``tst_kvm_run()`` function handles this issue correctly.
|
||||
|
||||
KVM Guest Library
|
||||
-----------------
|
||||
|
||||
The KVM guest library provides a minimal implementation of both the LTP
|
||||
test library and the standard C library functions. Do not try to include
|
||||
the usual LTP or C headers in guest payload code; it will not work.
|
||||
|
||||
Standard C Functions
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
``#include "kvm_test.h"``
|
||||
|
||||
The functions listed below are implemented according to the C standard:
|
||||
|
||||
* ``void *memset(void *dest, int val, size_t size)``
|
||||
* ``void *memzero(void *dest, size_t size)``
|
||||
* ``void *memcpy(void *dest, const void *src, size_t size)``
|
||||
* ``char *strcpy(char *dest, const char *src)``
|
||||
* ``char *strcat(char *dest, const char *src)``
|
||||
* ``size_t strlen(const char *str)``
|
||||
|
||||
LTP Library Functions
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
``#include "kvm_test.h"``
|
||||
|
||||
The KVM guest library currently provides the LTP functions for reporting test
|
||||
results. All standard result flags except for ``T*ERRNO`` are supported
|
||||
with the same rules as usual. However, printf-like formatting is not
|
||||
implemented yet.
|
||||
|
||||
* ``void tst_res(int result, const char *message)``
|
||||
* ``void tst_brk(int result, const char *message) __attribute__((noreturn))``
|
||||
|
||||
A handful of useful macros is also available:
|
||||
|
||||
* ``TST_TEST_TCONF(message)`` – Generates a test program that will simply print
|
||||
a ``TCONF`` message and exit. This is useful when the real test cannot be
|
||||
built due to missing dependencies or architecture limitations.
|
||||
|
||||
* ``ARRAY_SIZE(arr)`` – Returns the number of items in statically allocated
|
||||
array ``arr``.
|
||||
|
||||
* ``LTP_ALIGN(x, a)`` – Aligns integer ``x`` to be a multiple of ``a``, which
|
||||
must be a power of 2.
|
||||
|
||||
Architecture Independent Functions
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
``#include "kvm_test.h"``
|
||||
|
||||
Memory management in the KVM guest library currently uses only a primitive linear
|
||||
buffer for memory allocation. There are no checks whether the VM can allocate
|
||||
more memory, and the already allocated memory cannot be freed.
|
||||
|
||||
* ``void *tst_heap_alloc(size_t size)`` – Allocates a block of memory on the heap.
|
||||
|
||||
* ``void *tst_heap_alloc_aligned(size_t size, size_t align)`` – Allocates
|
||||
a block of memory on the heap with the starting address aligned to a given
|
||||
value.
|
||||
|
||||
x86 Specific Functions
|
||||
~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
``#include "kvm_test.h"``
|
||||
``#include "kvm_x86.h"``
|
||||
|
||||
* ``struct kvm_interrupt_frame`` – Opaque architecture-dependent structure which holds
|
||||
interrupt frame information. Use the functions below to get individual values:
|
||||
|
||||
* ``uintptr_t kvm_get_interrupt_ip(const struct kvm_interrupt_frame *ifrm)`` –
|
||||
Gets instruction pointer value from the interrupt frame structure. This may be
|
||||
the instruction which caused an interrupt or the one immediately after,
|
||||
depending on the interrupt vector semantics.
|
||||
|
||||
* ``int (*tst_interrupt_callback)(void *userdata, struct kvm_interrupt_frame *ifrm, unsigned long errcode)`` –
|
||||
Interrupt handler callback prototype. When an interrupt occurs, the assigned callback function
|
||||
will be passed the ``userdata`` pointer that was given
|
||||
to ``tst_set_interrupt_callback()``, interrupt frame ``ifrm`` and the error
|
||||
code ``errcode`` defined by the interrupt vector semantics. If the interrupt
|
||||
vector does not generate an error code, ``errcode`` will be set to zero.
|
||||
The callback function must return 0 if the interrupt was successfully
|
||||
handled and test execution should resume. A non-zero return value means that
|
||||
the interrupt could not be handled and the test will terminate with an error.
|
||||
|
||||
* ``void tst_set_interrupt_callback(unsigned int vector, tst_interrupt_callback func, void *userdata)`` –
|
||||
Registers a new interrupt handler callback function ``func`` for interrupt ``vector``. The ``userdata``
|
||||
argument is an arbitrary pointer that will be passed to ``func()`` every time
|
||||
it gets called. The previous interrupt handler callback will be removed.
|
||||
Setting ``func`` to ``NULL`` will remove any existing interrupt handler
|
||||
from ``vector``, and the interrupt will become a fatal error.
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
struct page_table_entry_pae {
|
||||
unsigned int present: 1;
|
||||
unsigned int writable: 1;
|
||||
unsigned int user_access: 1;
|
||||
unsigned int write_through: 1;
|
||||
unsigned int disable_cache: 1;
|
||||
unsigned int accessed: 1;
|
||||
unsigned int dirty: 1;
|
||||
unsigned int page_type: 1;
|
||||
unsigned int global: 1;
|
||||
unsigned int padding: 3;
|
||||
uint64_t address: 40;
|
||||
unsigned int padding2: 7;
|
||||
unsigned int prot_key: 4;
|
||||
unsigned int noexec: 1;
|
||||
} __attribute__((__packed__));
|
||||
|
||||
struct kvm_cpuid {
|
||||
unsigned int eax, ebx, ecx, edx;
|
||||
};
|
||||
|
||||
struct kvm_cregs {
|
||||
unsigned long cr0, cr2, cr3, cr4;
|
||||
};
|
||||
|
||||
struct kvm_sregs {
|
||||
uint16_t cs, ds, es, fs, gs, ss;
|
||||
};
|
||||
|
||||
``struct page_table_entry_pae`` is the page table entry structure for PAE and
|
||||
64-bit paging modes. See Intel® 64 and IA-32 Architectures Software
|
||||
Developer's Manual, Volume 3, Chapter 4 for an explanation of the fields.
|
||||
|
||||
* ``uintptr_t kvm_get_page_address_pae(const struct page_table_entry_pae *entry)``
|
||||
– Returns the physical address of the memory page referenced by the given
|
||||
page table ``entry``. Depending on memory mapping changes done by the test,
|
||||
the physical address may not be a valid pointer. The caller must determine
|
||||
whether the address points to another page table entry or a data page, using
|
||||
the known position in page table hierarchy and ``entry->page_type``. Returns
|
||||
zero if the ``entry`` does not reference any memory page.
|
||||
|
||||
* ``void kvm_set_segment_descriptor(struct segment_descriptor *dst, uint64_t baseaddr, uint32_t limit, unsigned int flags)`` -
|
||||
Fills the ``dst`` segment descriptor with given values. The maximum value
|
||||
of ``limit`` is ``0xfffff`` (inclusive) regardless of ``flags``.
|
||||
|
||||
* ``void kvm_parse_segment_descriptor(struct segment_descriptor *src, uint64_t *baseaddr, uint32_t *limit, unsigned int *flags)`` -
|
||||
Parses data in the ``src`` segment descriptor and copies them to variables
|
||||
pointed to by the other arguments. Any parameter except the first one can
|
||||
be ``NULL``.
|
||||
|
||||
* ``int kvm_find_free_descriptor(const struct segment_descriptor *table, size_t size)`` -
|
||||
Finds the first segment descriptor in ``table`` which does not have
|
||||
the ``SEGFLAG_PRESENT`` bit set. The function handles double-size descriptors
|
||||
correctly. Returns the index of the first available descriptor or -1 if all
|
||||
``size`` descriptors are taken.
|
||||
|
||||
* ``unsigned int kvm_create_stack_descriptor(struct segment_descriptor *table, size_t tabsize, void *stack_base)`` -
|
||||
A convenience function for registering a stack segment descriptor. It will
|
||||
automatically find a free slot in ``table`` and fill the necessary flags.
|
||||
The ``stack_base`` pointer must point to the bottom of the stack.
|
||||
|
||||
* ``void kvm_get_cpuid(unsigned int eax, unsigned int ecx, struct kvm_cpuid *buf)`` –
|
||||
Executes the CPUID instruction with the given
|
||||
``eax`` and ``ecx`` arguments and stores the results in ``buf``.
|
||||
|
||||
* ``void kvm_read_cregs(struct kvm_cregs *buf)`` – Copies the current values
|
||||
of control registers to ``buf``.
|
||||
|
||||
* ``void kvm_read_sregs(struct kvm_sregs *buf)`` - Copies the current values
|
||||
of segment registers to ``buf``.
|
||||
|
||||
* ``uint64_t kvm_rdmsr(unsigned int msr)`` – Returns the current value
|
||||
of model-specific register ``msr``.
|
||||
|
||||
* ``void kvm_wrmsr(unsigned int msr, uint64_t value)`` – Stores ``value``
|
||||
into model-specific register ``msr``.
|
||||
|
||||
* ``void kvm_exit(void) __attribute__((noreturn))`` – Terminates the test.
|
||||
Similar to calling ``exit(0)`` in a regular LTP test, although ``kvm_exit()``
|
||||
will terminate only one iteration of the test, not the whole host process.
|
||||
|
||||
See Intel® 64 and IA-32 Architectures Software Developer's Manual
|
||||
for documentation of standard and model-specific x86 registers.
|
||||
|
||||
AMD SVM Helper Functions
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
``#include "kvm_test.h"``
|
||||
``#include "kvm_x86.h"``
|
||||
``#include "kvm_x86_svm.h"``
|
||||
|
||||
The KVM guest library provides basic helper functions for creating and running
|
||||
nested virtual machines using the AMD SVM technology.
|
||||
|
||||
.. _example-code-to-execute-nested-vm:
|
||||
|
||||
.. rubric:: Example Code to Execute Nested VM
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
int guest_main(void)
|
||||
{
|
||||
...
|
||||
return 0;
|
||||
}
|
||||
|
||||
void main(void)
|
||||
{
|
||||
struct kvm_svm_vcpu *vm;
|
||||
|
||||
kvm_init_svm();
|
||||
vm = kvm_create_svm_vcpu(guest_main, 1);
|
||||
kvm_svm_vmrun(vm);
|
||||
}
|
||||
|
||||
* ``int kvm_is_svm_supported(void)`` - Returns a non-zero value if the CPU
|
||||
supports AMD SVM; otherwise, returns 0.
|
||||
|
||||
* ``int kvm_get_svm_state(void)`` - Returns a non-zero value if SVM is currently
|
||||
enabled; otherwise, returns 0.
|
||||
|
||||
* ``void kvm_set_svm_state(int enabled)`` - Enables or disables SVM according
|
||||
to the argument. If SVM is disabled by the host or not supported, the test will exit
|
||||
with ``TCONF``.
|
||||
|
||||
* ``void kvm_init_svm(void)`` - Enables and fully initializes SVM, including
|
||||
allocating and setting up the host save area VMCB. If SVM is disabled by the host or
|
||||
not supported, the test will exit with ``TCONF``.
|
||||
|
||||
* ``struct kvm_vmcb *kvm_alloc_vmcb(void)`` - Allocates a new VMCB structure
|
||||
with correct memory alignment and fills it with zeroes.
|
||||
|
||||
* ``void kvm_vmcb_set_intercept(struct kvm_vmcb *vmcb, unsigned int id, unsigned int state)`` -
|
||||
Sets SVM intercept bit ``id`` to the given ``state``.
|
||||
|
||||
* ``void kvm_init_guest_vmcb(struct kvm_vmcb *vmcb, uint32_t asid, uint16_t ss, void *rsp, int (*guest_main)(void))`` -
|
||||
Initializes a new SVM virtual machine. The ``asid`` parameter is the nested
|
||||
page table ID. The ``ss`` and ``rsp`` parameters set the stack segment and stack
|
||||
pointer values, respectively. The ``guest_main`` parameter sets the code entry
|
||||
point of the virtual machine. All control registers, segment registers
|
||||
(except stack segment register), GDTR and IDTR will be copied
|
||||
from the current CPU state.
|
||||
|
||||
* ``struct kvm_svm_vcpu *kvm_create_svm_vcpu(int (*guest_main)(void), int alloc_stack)`` -
|
||||
A convenience function for allocating and initializing a new SVM virtual CPU.
|
||||
The ``guest_main`` parameter is passed to ``kvm_init_guest_vmcb()``;
|
||||
the ``alloc_stack`` parameter controls whether a new 8KB stack will be
|
||||
allocated and registered in GDT. Interception will be enabled for ``VMSAVE``
|
||||
and ``HLT`` instructions. If you set ``alloc_stack`` to zero, you must configure
|
||||
the stack segment register and stack pointer manually.
|
||||
|
||||
* ``void kvm_svm_vmrun(struct kvm_svm_vcpu *cpu)`` - Starts or continues execution
|
||||
of a nested virtual machine. Be aware that FPU state is not saved. Do not use
|
||||
floating point types or values in nested guest code. Also, do not use
|
||||
``tst_res()`` or ``tst_brk()`` functions in nested guest code.
|
||||
|
||||
See AMD64 Architecture Programmer's Manual Volume 2 for documentation
|
||||
of the Secure Virtual Machine (SVM) technology.
|
||||
|
||||
KVM Guest Environment
|
||||
---------------------
|
||||
|
||||
KVM guest payload execution begins with bootstrap code which will perform
|
||||
the minimal guest environment setup required for running C code:
|
||||
|
||||
* Activates the appropriate CPU execution mode (IA-32 protected mode
|
||||
on 32-bit x86 or the 64-bit mode on x86_64).
|
||||
* Creates an identity mapping (virtual address = physical address) of the lower
|
||||
2GB memory region, even if parts of the region are not backed by any host
|
||||
memory buffers. The memory region above the 2GB threshold is left unmapped
|
||||
except for one memory page reserved for the ``struct tst_kvm_result`` buffer.
|
||||
* Initializes an 8KB stack.
|
||||
* Installs default interrupt handlers for standard CPU exception vectors.
|
||||
|
||||
When the environment setup is complete, bootstrap will call the ``void main(void)``
|
||||
function implemented by the test program. To finish execution of the guest payload,
|
||||
the test can either return from the ``main()`` function or call ``kvm_exit()``
|
||||
at any point.
|
||||
@@ -0,0 +1,7 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
.. Include headers in this file with:
|
||||
.. .. kernel-doc:: ../../include/tst_test.h
|
||||
|
||||
Developing using network API
|
||||
============================
|
||||
@@ -0,0 +1,4 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
LTP shell API
|
||||
=============
|
||||
@@ -0,0 +1,209 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
Build system
|
||||
============
|
||||
|
||||
The following document briefly describes the steps and methodologies used for
|
||||
the new and improved Makefile system.
|
||||
|
||||
The Problem
|
||||
-----------
|
||||
|
||||
The problem with the old Makefile system is that it was very difficult to
|
||||
maintain and it lacked any sense of formal structure, thus developing for LTP
|
||||
and including new targets was more difficult than it should have been
|
||||
(maintenance). Furthermore, proper option-based cross-compilation was
|
||||
impossible due to the fact that the Makefiles didn't support a prefixing
|
||||
system, and the appropriate implicit / static rules hadn't been configured to
|
||||
compile into multiple object directories for out-of-tree build support (ease of
|
||||
use / functionality). Finally, there wasn't a means to setup dependencies
|
||||
between components, such that if a component required ``libltp.a`` in order to
|
||||
compile, it would go off and compile ``libltp.a`` first (ease of use).
|
||||
|
||||
These items needed to be fixed to reduce maintenance nightmares for the
|
||||
development community contributing to LTP, and the project maintainers.
|
||||
|
||||
Design
|
||||
------
|
||||
|
||||
The system was designed such that including a single GNU Makefile compatible
|
||||
set in each new directory component is all that's essentially required to
|
||||
build the system.
|
||||
|
||||
Say you had a directory like the following (with ``.c`` files in them which
|
||||
directly tie into applications, e.g. baz.c -> baz):
|
||||
|
||||
.. code-block::
|
||||
|
||||
.../foo/
|
||||
|--> Makefile
|
||||
|
|
||||
--> bar/
|
||||
|
|
||||
--> Makefile
|
||||
|
|
||||
--> baz.c
|
||||
|
||||
.. code-block:: make
|
||||
:caption: .../foo/Makefile
|
||||
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
top_srcdir ?= ..
|
||||
|
||||
include $(top_srcdir)/include/mk/env_pre.mk
|
||||
include $(top_srcdir)/include/mk/generic_trunk_target.mk
|
||||
|
||||
.. code-block:: make
|
||||
:caption: .../foo/bar/Makefile
|
||||
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
top_srcdir ?= ../..
|
||||
|
||||
include $(top_srcdir)/include/mk/env_pre.mk
|
||||
include $(top_srcdir)/include/mk/generic_leaf_target.mk
|
||||
|
||||
Kernel Modules
|
||||
--------------
|
||||
|
||||
Some of the tests need to build kernel modules, happily LTP has
|
||||
infrastructure for this.
|
||||
|
||||
.. code-block:: make
|
||||
|
||||
ifneq ($(KERNELRELEASE),)
|
||||
|
||||
obj-m := module01.o
|
||||
|
||||
else
|
||||
|
||||
top_srcdir ?= ../../../..
|
||||
include $(top_srcdir)/include/mk/testcases.mk
|
||||
|
||||
REQ_VERSION_MAJOR := 2
|
||||
REQ_VERSION_PATCH := 6
|
||||
MAKE_TARGETS := test01 test02 module01.ko
|
||||
|
||||
include $(top_srcdir)/include/mk/module.mk
|
||||
include $(top_srcdir)/include/mk/generic_leaf_target.mk
|
||||
|
||||
endif
|
||||
|
||||
This is a Makefile example that allows you to build kernel modules inside LTP.
|
||||
The prerequisites for the build are detected by the ``configure`` script.
|
||||
|
||||
The ``REQ_VERSION_MAJOR`` and ``REQ_VERSION_PATCH`` describe minimal kernel
|
||||
version for which the build system tries to build the module.
|
||||
|
||||
The build system is also forward compatible with changes in Linux kernel
|
||||
internal API so that, if module fails to build, the failure is ignored both on
|
||||
build and installation. If the userspace counterpart of the test fails to load
|
||||
the module because the file does not exists, the test is skipped.
|
||||
|
||||
Note the ``ifneq($(KERNELRELEASE),)``. The reason it exists, it is that the
|
||||
Makefile is executed twice: once by LTP build system and once by kernel kbuild,
|
||||
see :kernel_doc:`kbuild/modules` in the Linux kernel documentation for details
|
||||
on external module build.
|
||||
|
||||
Make Rules and Make Variables
|
||||
-----------------------------
|
||||
|
||||
When using make rules, avoid writing ad hoc rules like:
|
||||
|
||||
.. code-block:: make
|
||||
|
||||
[prog]: [dependencies]
|
||||
cc -I../../include $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) $(LDLIBS) \
|
||||
-o [prog] [dependencies]
|
||||
|
||||
This makes cross-compilation and determinism difficult, if not impossible.
|
||||
Besides, implicit rules are your friends and as long as you use ``MAKEOPTS=;``
|
||||
in the top-level caller (or do ``$(subst r,$(MAKEOPTS)``) to remove ``-r``),
|
||||
the compile will complete successfully, assuming all other prerequisites have
|
||||
been fulfilled (libraries, headers, etc).
|
||||
|
||||
.. list-table::
|
||||
:header-rows: 1
|
||||
|
||||
* - Variable
|
||||
- Explanation
|
||||
|
||||
* - $(AR)
|
||||
- The library archiver
|
||||
|
||||
* - $(CC)
|
||||
- The system C compiler
|
||||
|
||||
* - $(CCP)
|
||||
- The system C preprocessor
|
||||
|
||||
* - $(CFLAGS)
|
||||
- C compiler flags
|
||||
|
||||
* - $(CPPFLAGS)
|
||||
- Preprocessor flags, e.g. ``-I`` arguments
|
||||
|
||||
* - $(DEBUG_CFLAGS)
|
||||
- Debug flags to pass to ``$(CC)``, ``-g``, etc
|
||||
|
||||
* - $(KVM_LD)
|
||||
- Special linker for wrapping KVM payload binaries into linkable object
|
||||
files. Defaults to ``$(LD)``. Change this variable if the KVM Makefile
|
||||
fails to build files named ``*-payload.o``
|
||||
|
||||
* - $(LD)
|
||||
- The system linker (typically ``$(CC)``, but not necessarily)
|
||||
|
||||
* - $(LDFLAGS)
|
||||
- What to pass in to the linker, including ``-L`` arguments and other ld
|
||||
arguments, apart from ``-l`` library includes (see ``$(LDLIBS)``).
|
||||
This should be done in the ``$(CC)`` args passing style when
|
||||
``LD := $(CC)``, e.g. ``-Wl,-foo``, as opposed to ``-foo``
|
||||
|
||||
* - $(LDLIBS)
|
||||
- Libraries to pass to the linker (e.g. ``-lltp``, etc)
|
||||
|
||||
* - $(LTPLDLIBS)
|
||||
- LTP internal libraries i.e. these in libs/ directory
|
||||
|
||||
* - $(OPT_CFLAGS)
|
||||
- Optimization flags to pass into the C compiler, ``-O2``, etc. If you
|
||||
specify ``-O2`` or higher, you should also specify
|
||||
``-fno-strict-aliasing``, because of gcc fstrict-aliasing optimization
|
||||
bugs in the tree optimizer. Search for **fstrict-aliasing optimization
|
||||
bug** with your favorite search engine.
|
||||
|
||||
Examples of more recent bugs: tree-optimization/17510
|
||||
and tree-optimization/39100.
|
||||
|
||||
Various bugs have occurred in the past due to buggy logic in the
|
||||
tree-optimization portion of the gcc compiler, from 3.3.x to 4.4.
|
||||
|
||||
* - $(RANLIB)
|
||||
- What to run after archiving a library
|
||||
|
||||
* - $(WCFLAGS)
|
||||
- Warning flags to pass to ``$(CC)``, e.g. ``-Werror``, ``-Wall``, etc.
|
||||
|
||||
Make System Variables
|
||||
---------------------
|
||||
|
||||
A series of variables are used within the make system that direct what actions
|
||||
need to be taken. Rather than listing the variables here, please refer to the
|
||||
comments contained in :master:`include/mk/env_pre.mk`.
|
||||
|
||||
Guidelines and Recommendations
|
||||
------------------------------
|
||||
|
||||
Of course, GNU Make manual is the key to understand the Make system, but
|
||||
following manuals are probably the most important:
|
||||
|
||||
* `Implicit Rules <http://www.gnu.org/software/make/manual/make.html#Implicit-Rules>`_
|
||||
* `Variables and Expansion <http://www.gnu.org/software/make/manual/make.html#Using-Variables>`_
|
||||
* `Origin Use <http://www.gnu.org/software/make/manual/make.html#Origin-Function>`_
|
||||
* `VPath Use <http://www.gnu.org/software/make/manual/make.html#Directory-Search>`_
|
||||
|
||||
.. warning::
|
||||
|
||||
Rebuild from scratch before committing anything in the build system.
|
||||
@@ -0,0 +1,23 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
Debugging
|
||||
=========
|
||||
|
||||
This section explains some tricks which can be used to debug test binaries.
|
||||
|
||||
Debug messages
|
||||
--------------
|
||||
|
||||
The LTP framework supports ``TDEBUG`` flag test debug messages. These
|
||||
messages can be enabled using the ``-D`` parameter or setting ``LTP_ENABLE_DEBUG=1``
|
||||
environment variable (see :doc:`../users/setup_tests`).
|
||||
|
||||
Tracing and debugging syscalls
|
||||
------------------------------
|
||||
|
||||
The new test library runs the actual test (i.e. the ``test()`` function) in a
|
||||
forked process. To get stack trace of a crashing test in ``gdb`` it's needed to
|
||||
`set follow-fork-mode child <https://sourceware.org/gdb/current/onlinedocs/gdb.html/Forks.html>`_.
|
||||
|
||||
To trace the test, please use ``strace -f`` to enable tracing also for the
|
||||
forked processes.
|
||||
@@ -0,0 +1,55 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
Documentation
|
||||
=============
|
||||
|
||||
This section explains how to use and develop the LTP documentation. The current
|
||||
documentation format is written using
|
||||
`reStructedText <https://www.sphinx-doc.org/en/master/usage/restructuredtext/index.html>`_
|
||||
and it's built on top of `Sphinx <https://www.sphinx-doc.org/en/master/>`_.
|
||||
|
||||
Building documentation
|
||||
~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Before building, make sure you have python3 ``virtualenv`` module installed.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
# run configure to be able to compile doc dependencies in metadata/
|
||||
make autotools
|
||||
./configure
|
||||
cd doc
|
||||
|
||||
# prepare virtual environment
|
||||
python3 -m virtualenv .venv
|
||||
. .venv/bin/activate
|
||||
pip install -r requirements.txt
|
||||
|
||||
# build documentation
|
||||
make
|
||||
|
||||
Once the procedure has been completed, documentation will be visible at
|
||||
``doc/html/index.html``.
|
||||
|
||||
.. warning::
|
||||
|
||||
Documentation requires ``Python >= 3.6``.
|
||||
The current :master:`.readthedocs.yml` workflow is using ``Python 3.12``,
|
||||
it is tested in GitHub Actions :master:`.github/workflows/ci-sphinx-doc.yml`.
|
||||
|
||||
Validating spelling
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
To check documentation words spelling, we provide support for
|
||||
`aspell <http://aspell.net/>`_, so make sure that it's installed. The
|
||||
documentation can be tested via ``make spelling`` command. Output will be
|
||||
visible in the ``doc/build`` folder and, if any error will be found, a warning
|
||||
message will be shown.
|
||||
|
||||
C API documentation
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The C API documentation is generated from headers using
|
||||
`kernel-doc <https://return42.github.io/linuxdoc/linuxdoc-howto/kernel-doc-syntax.html>`_
|
||||
syntax which is supported by Sphinx via
|
||||
`linuxdoc <https://pypi.org/project/linuxdoc/>`_ extension.
|
||||
@@ -0,0 +1,45 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
LTP Library guidelines
|
||||
======================
|
||||
|
||||
General Rules
|
||||
-------------
|
||||
|
||||
For extending the LTP library API it applies the same general rules as
|
||||
for :doc:`writing tests <../developers/writing_tests>`
|
||||
(with strong focus on readability and simplicity), plus:
|
||||
|
||||
#. LTP library tests must go inside :master:`lib/newlib_tests` directory
|
||||
#. LTP documentation has to be updated according to API changes
|
||||
#. Do not add new API functions to the old API. Add new functions to
|
||||
``tst_.[ch]`` files.
|
||||
|
||||
Shell API
|
||||
---------
|
||||
|
||||
API source code is in :master:`testcases/lib/tst_test.sh`,
|
||||
:master:`testcases/lib/tst_security.sh` and :master:`testcases/lib/tst_net.sh`.
|
||||
|
||||
Changes in the shell API should not introduce uncommon dependencies
|
||||
(use basic commands installed everywhere by default).
|
||||
|
||||
Shell libraries
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
Aside from shell API libraries in :master:`testcases/lib` directory, it's
|
||||
worth putting common code for a group of tests into a shell library.
|
||||
The filename should end with ``_lib.sh`` and the library should load
|
||||
``tst_test.sh`` or ``tst_net.sh``.
|
||||
|
||||
Shell libraries should have conditional expansion for ``TST_SETUP`` or
|
||||
``TST_CLEANUP``, to avoid surprises when test specific setup/cleanup function is
|
||||
redefined by shell library.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
# ipsec_lib.sh
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
TST_SETUP="${TST_SETUP:-ipsec_lib_setup}"
|
||||
...
|
||||
. tst_test.sh
|
||||
@@ -0,0 +1,50 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
Setting up the Mailing list
|
||||
===========================
|
||||
|
||||
Before using ``git send-email``, you need to set up your email client to send
|
||||
emails from the command line. This typically involves configuring an SMTP server
|
||||
and authentication details.
|
||||
|
||||
Open a terminal and configure Git with your email settings using the following
|
||||
commands:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
git config --global sendemail.from "Your Name <your_email@example.com>"
|
||||
git config --global sendemail.smtpserver "smtp.example.com"
|
||||
git config --global sendemail.smtpuser "your_email@example.com"
|
||||
git config --global sendemail.smtpserverport 587
|
||||
git config --global sendemail.smtpencryption tls
|
||||
|
||||
Replace ``smtp.example.com`` with the SMTP server address provided by your email
|
||||
provider. Replace ``your_email@example.com`` with your email address. Adjust the
|
||||
SMTP port and encryption settings according to your email provider's
|
||||
requirements.
|
||||
|
||||
To test the configuration you can use ``--dry-run`` parameter.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
git send-email --dry-run --to "ltp@lists.linux.it" --subject "Test Email" --body "This is a test email." HEAD^
|
||||
|
||||
Depending on your SMTP server's configuration, you may need to authenticate
|
||||
before sending emails. If required, configure authentication settings using:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
git config --global sendemail.smtpuser "your_email@example.com"
|
||||
git config --global sendemail.smtppass "your_password"
|
||||
|
||||
Replace ``your_email@example.com`` with your email address and ``your_password``
|
||||
with your email account password.
|
||||
|
||||
For any corner case, please take a look at the
|
||||
`email + git <https://git-send-email.io/>`_ documentation.
|
||||
|
||||
.. note::
|
||||
|
||||
This method still works in most of the cases, but nowadays we often
|
||||
require to setup a two factor authentication. If this is the case, please
|
||||
consider setting up Git accordingly.
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,537 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
Writing tests
|
||||
=============
|
||||
|
||||
This document describes LTP guidelines and it's intended for anybody who wants
|
||||
to write or to modify a LTP testcase. It's not a definitive guide and it's not,
|
||||
by any means, a substitute for common sense.
|
||||
|
||||
Guide to clean and understandable code
|
||||
--------------------------------------
|
||||
|
||||
Testcases require that the source code is easy to follow. When a test starts to
|
||||
fail, the failure has to be analyzed and clean test codebase makes this task
|
||||
much easier and quicker.
|
||||
|
||||
Keep things simple
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
It's worth to keep testcases simple or, better, as simple as possible.
|
||||
|
||||
The kernel and libc are tricky beasts and the complexity imposed by their
|
||||
interfaces is quite high. Concentrate on the interface you want to test and
|
||||
follow the UNIX philosophy.
|
||||
|
||||
It's a good idea to make the test as self-contained as possible too, ideally
|
||||
tests should not depend on tools or libraries that are not widely available.
|
||||
|
||||
Do not reinvent the wheel!
|
||||
|
||||
* Use LTP standard interface
|
||||
* Do not add custom PASS/FAIL reporting functions
|
||||
* Do not write Makefiles from scratch, use LTP build system instead
|
||||
* Etc.
|
||||
|
||||
Keep functions and variable names short
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Choosing a good name for an API functions or even variables is a difficult
|
||||
task do not underestimate it.
|
||||
|
||||
There are a couple of customary names for different things that help people to
|
||||
understand code, for example:
|
||||
|
||||
* For loop variables are usually named with a single letter ``i``, ``j``, ...
|
||||
* File descriptors ``fd`` or ``fd_foo``.
|
||||
* Number of bytes stored in file are usually named as ``size`` or ``len``
|
||||
* Etc.
|
||||
|
||||
Do not over-comment
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Comments can sometimes save your day, but they can easily do more harm than
|
||||
good. There has been several cases where comments and actual implementation
|
||||
drifted slowly apart which yielded into API misuses and hard to find bugs.
|
||||
Remember there is only one thing worse than no documentation: wrong
|
||||
documentation.
|
||||
|
||||
Ideally, everybody should write code that is obvious, which unfortunately isn't
|
||||
always possible. If there is a code that requires to be commented, keep it
|
||||
short and to the point. These comments should explain *why* and not *how*
|
||||
things are done.
|
||||
|
||||
Never ever comment the obvious.
|
||||
|
||||
In case of LTP testcases, it's customary to add an `RST
|
||||
<https://www.sphinx-doc.org/en/master/usage/restructuredtext/basics.html>`_
|
||||
formatted comment paragraph with high-level test description at the beginning
|
||||
of the file right under the GPL SPDX header. This helps other people to
|
||||
understand the overall goal of the test before they dive into the technical
|
||||
details. It's also exported into generated documentation hence it should mostly
|
||||
explain what is tested.
|
||||
|
||||
DRY (Code duplication)
|
||||
~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Copy & paste is a good servant but very poor master. If you are about to copy a
|
||||
large part of the code from one testcase to another, think what would happen if
|
||||
you find bug in the code that has been copied all around the tree. What about
|
||||
moving it to a library instead?
|
||||
|
||||
The same goes for short but complicated parts, whenever you are about to copy &
|
||||
paste a syscall wrapper that packs arguments accordingly to machine
|
||||
architecture or similarly complicated code, put it into a header instead.
|
||||
|
||||
C coding style
|
||||
--------------
|
||||
|
||||
LTP adopted `Linux kernel coding style <https://www.kernel.org/doc/html/latest/process/coding-style.html>`_.
|
||||
Run ``make check`` in the test's directory and/or use ``make check-$TCID``, it
|
||||
uses (among other checks) our vendoring version of
|
||||
`checkpatch.pl <https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/plain/scripts/checkpatch.pl>`_
|
||||
script from kernel git tree.
|
||||
|
||||
.. note::
|
||||
If ``make check`` does not report any problems, the code still may be wrong
|
||||
as all tools used for checking only look for common mistakes.
|
||||
|
||||
The following linting code can be found when we run ``make check``:
|
||||
|
||||
.. list-table::
|
||||
:header-rows: 1
|
||||
|
||||
* - Linting code
|
||||
- Message
|
||||
- Explanation
|
||||
|
||||
* - LTP-001
|
||||
- Library source files have ``tst_`` prefix
|
||||
- API source code is inside headers in ``include/{empty}*.h``,
|
||||
``include/lapi/{empty}*.h`` (backward compatibility for old kernel and
|
||||
libc) and C sources in ``lib/{empty}*.c``. Files must have ``tst_``
|
||||
prefix.
|
||||
|
||||
* - LTP-002
|
||||
- ``TST_RET`` and ``TST_ERR`` are never modified by test library functions
|
||||
- The test author is guaranteed that the test API will not modify these
|
||||
variables. This prevents silent errors where the return value and
|
||||
errno are overwritten before the test has chance to check them.
|
||||
|
||||
The macros which are clearly intended to update these variables. That
|
||||
is ``TEST`` and those in :master:`include/tst_test_macros.h`. Are of
|
||||
course allowed to update these variables.
|
||||
|
||||
* - LTP-003
|
||||
- Externally visible library symbols have the ``tst_`` prefix
|
||||
- Functions, types and variables in the public test API should have the
|
||||
``tst_`` prefix. With some exceptions for symbols already prefixed with
|
||||
``safe_`` or ``ltp_``.
|
||||
|
||||
Static (private) symbols should not have the prefix.
|
||||
|
||||
* - LTP-004
|
||||
- Test executable symbols are marked ``static``
|
||||
- Test executables should not export symbols unnecessarily. This means
|
||||
that all top-level variables and functions should be marked with the
|
||||
``static`` keyword. The only visible symbols should be those included
|
||||
from shared object files.
|
||||
|
||||
* - LTP-005
|
||||
- Array must terminate with a sentinel value (i.e. ``NULL`` or ``{}``)
|
||||
- When defining arrays in the :ref:`struct tst_test` structure, we need to
|
||||
end the array items with a sentinel ``NULL`` value.
|
||||
|
||||
Shell coding style
|
||||
------------------
|
||||
|
||||
When writing testcases in shell, write in *portable shell* only, it's a good
|
||||
idea to try to run the test using alternative shell (alternative to bash, for
|
||||
example dash) too.
|
||||
|
||||
*Portable shell* means Shell Command Language as defined by POSIX with an
|
||||
exception of few widely used extensions, namely **local** keyword used inside of
|
||||
functions and ``-o`` and ``-a`` test parameters (that are marked as obsolete in
|
||||
POSIX).
|
||||
|
||||
You can either try to run the testcases in Debian which has ``/bin/sh`` pointing
|
||||
to ``dash`` by default, or to install ``dash`` on your favorite distribution,
|
||||
then use it to run tests. If your distribution lacks ``dash`` package, you can
|
||||
always compile it from `sources <http://gondor.apana.org.au/~herbert/dash/files/>`_.
|
||||
|
||||
Run ``make check`` in the test's directory and/or use ``make check-$TCID.sh``.
|
||||
It uses (among other checks) our vendoring version of
|
||||
`checkbashism.pl <https://salsa.debian.org/debian/devscripts/raw/master/scripts/checkbashisms.pl>`_
|
||||
from Debian that is used to check for non-portable shell code.
|
||||
|
||||
.. note::
|
||||
|
||||
If ``make check`` does not report any problems the code still may be wrong,
|
||||
as ``checkbashisms.pl`` is used for checking only common mistakes.
|
||||
|
||||
Here there are some common sense style rules for shell
|
||||
|
||||
* Keep lines under 80 chars
|
||||
* Use tabs for indentation
|
||||
* Keep things simple, avoid unnecessary subshells
|
||||
* Don't do confusing things (i.e. don't name your functions like common shell
|
||||
commands, etc.)
|
||||
* Quote variables
|
||||
* Be consistent
|
||||
|
||||
3 Backwards compatibility
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
LTP test should be as backward compatible as possible. Think of an enterprise
|
||||
distributions with long term support (more than five years since the initial
|
||||
release) or of an embedded platform that needs to use several years old
|
||||
toolchain supplied by the manufacturer.
|
||||
|
||||
Therefore LTP test for more current features should be able to cope with older
|
||||
systems. It should at least compile fine and if it's not appropriate for the
|
||||
configuration it should return ``TCONF``.
|
||||
|
||||
There are several types of checks we use:
|
||||
|
||||
* The *configure script* is usually used to detect availability of a function
|
||||
declarations in system headers. It's used to disable tests at compile time or
|
||||
to enable fallback definitions.
|
||||
|
||||
* Checking the ``errno`` value is another type of runtime check. Most of the
|
||||
syscalls returns either ``EINVAL`` or ``ENOSYS`` when syscall was not
|
||||
implemented or was disabled upon kernel compilation.
|
||||
|
||||
* LTP has kernel version detection that can be used to disable tests at runtime.
|
||||
Unfortunately, the kernel version does not always corresponds to a well
|
||||
defined feature set, as distributions tend to backport hundreds of patches
|
||||
while the kernel version stays the same. Use with caution.
|
||||
|
||||
* Lately, we added a kernel ``.config`` parser. A test can define a boolean
|
||||
expression of kernel config variables that has to be satisfied in order to run
|
||||
a test. At the moment, this is mostly used for kernel namespaces.
|
||||
|
||||
* Sometimes it makes sense to define a few macros instead of creating a
|
||||
configure test. One example is Linux specific POSIX clock ids in
|
||||
:master:`include/lapi/posix_clocks.h`.
|
||||
|
||||
Dealing with messed up legacy code
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
LTP still contains a lot of old and messy code and we are cleaning it up as
|
||||
fast as we can but, despite the decade of efforts, there is still a lot of it.
|
||||
If you start modifying old or a messy testcase and your changes are more
|
||||
complicated than simple typo fixes, you should convert the test into a new
|
||||
library first.
|
||||
|
||||
It's also much easier to review the changes if you split them into a smaller
|
||||
logical groups. The same goes for moving files: if you need to rename or to move
|
||||
files, do it in a separate patch.
|
||||
|
||||
License
|
||||
~~~~~~~
|
||||
|
||||
Code contributed to LTP should be licensed under GPLv2+ (GNU GPL version 2 or
|
||||
any later version).
|
||||
|
||||
Use ``SPDX-License-Identifier: GPL-2.0-or-later``
|
||||
|
||||
LTP Structure
|
||||
-------------
|
||||
|
||||
The structure of LTP is quite simple. Each test is a binary written either in
|
||||
portable shell or C. The test gets a configuration via environment variables
|
||||
and/or command line parameters, it prints additional information into the
|
||||
stdout and reports overall success/failure via the exit value.
|
||||
|
||||
Tests are generally placed under the :master:`testcases` directory. Everything that
|
||||
is a syscall or (slightly confusingly) libc syscall wrapper, goes under
|
||||
:master:`testcases/kernel/syscalls/`.
|
||||
|
||||
There is also :master:`testcases/open_posix_testsuite/` which is a well maintained
|
||||
fork of the Open POSIX testsuite project, that has been dead since 2005.
|
||||
|
||||
We also have a number of directories with tests for more specific features, such
|
||||
as containers, etc.
|
||||
|
||||
Runtest Files
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
The list of tests to be executed is stored in runtest files under the
|
||||
:master:`runtest` directory. The default set of runtest files to be executed is
|
||||
stored in :master:`scenario_groups/default`. When you add a test, you should add
|
||||
corresponding entries into some runtest file(s) as well.
|
||||
|
||||
Each line of runtest file contains one test. The first item is the test name.
|
||||
All other items, separated by space will be executed as a command.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
shell_test01 echo "SUCCESS" | shell_pipe01.sh
|
||||
splice02 splice02 -s 20
|
||||
|
||||
Blank lines and lines starting with a ``#`` (comments) are ignored.
|
||||
|
||||
Syscalls tests, placed under :master:`testcases/kernel/syscalls/`, use
|
||||
:master:`runtest/syscalls` file. For kernel related tests for memory management we
|
||||
have :master:`runtest/mm`, etc.
|
||||
|
||||
.. note::
|
||||
|
||||
runtest files should have one entry per a test. Creating a
|
||||
wrapper that runs all your tests and adding it as a single test
|
||||
into runtest file is strongly discouraged.
|
||||
|
||||
Datafiles
|
||||
---------
|
||||
|
||||
If your test needs data files, these should be put into a subdirectory
|
||||
named ``datafiles`` and installed into the ``testcases/data/$TCID`` directory.
|
||||
This will require to add ``INSTALL_DIR := testcases/data/TCID`` into
|
||||
correspondent ``datafiles/Makefile``.
|
||||
|
||||
You can obtain path to datafiles via ``$TST_DATAROOT`` provided by ``test.sh``
|
||||
or via C function ``tst_dataroot()`` provided by libltp:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
const char *dataroot = tst_dataroot();
|
||||
|
||||
Datafiles can also be accessed as ``$LTPROOT/testcases/data/$TCID/...``,
|
||||
but ``$TST_DATAROOT`` and ``tst_dataroot()`` are preferred, as these can be used
|
||||
when running testcases directly in git tree as well as from install location.
|
||||
|
||||
Sub-executables
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
If your test needs to execute a binary, place it in the same directory of the
|
||||
testcase and name the binary with ``$TESTNAME_`` prefix, where ``$TESTNAME`` is
|
||||
the name of the test binary. Once the test is executed by the framework, the
|
||||
path to the directory with all LTP binaries is added to the ``$PATH`` and you
|
||||
can execute it via its name.
|
||||
|
||||
.. note::
|
||||
|
||||
If you need to execute a test from the LTP tree, you can add ``PATH`` to
|
||||
the current directory with ``PATH="$PATH:$PWD" ./foo01``.
|
||||
|
||||
Test Contribution Checklist
|
||||
---------------------------
|
||||
|
||||
#. Test compiles and it runs fine (check with ``-i 10`` and ``-i 0`` too)
|
||||
#. ``make check`` should not emit any warnings for the test you are working on
|
||||
(hint: run it in the test's directory and/or use ``make check-$TCID``)
|
||||
#. The runtest entries are in place
|
||||
#. New test binaries are added into the corresponding ``.gitignore`` files
|
||||
#. Patches apply over the latest git
|
||||
|
||||
About .gitignore files
|
||||
~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
There are numerous ``.gitignore`` files in the LTP tree. Usually, there is a
|
||||
``.gitignore`` file for a group of tests. The reason of this setup is simple:
|
||||
it's easier to maintain a ``.gitignore`` file per tests' directory, rather
|
||||
than having a single file in the project root directory. In this way, we don't
|
||||
have to update all the gitignore files when moving directories, and they get
|
||||
deleted automatically when a directory with tests is removed.
|
||||
|
||||
Testing pre-release kernel features
|
||||
-----------------------------------
|
||||
|
||||
Tests for features not yet in the mainline kernel release are accepted. However,
|
||||
they must be added only to :master:`runtest/staging`. Once a feature is part
|
||||
of the stable kernel ABI, the associated test must be moved out of staging.
|
||||
|
||||
Testing builds with GitHub Actions
|
||||
----------------------------------
|
||||
|
||||
Master branch is tested in GitHub :repo:`actions`
|
||||
to ensure LTP builds in various distributions, including old, current and
|
||||
bleeding edge. ``gcc`` and ``clang`` toolchains are also tested for various
|
||||
architectures using cross-compilation. For a full list of tested distros, please
|
||||
check :master:`.github/workflows/ci-docker-build.yml`.
|
||||
|
||||
.. note::
|
||||
|
||||
Passing the GitHub Actions CI means that LTP compiles in a variety of
|
||||
different distributions on their **newest releases**.
|
||||
The CI also checks for code linting, running ``make check`` in the whole
|
||||
LTP project.
|
||||
|
||||
LTP C And Shell Test API Comparison
|
||||
-----------------------------------
|
||||
|
||||
.. list-table::
|
||||
:header-rows: 1
|
||||
|
||||
* - C API :ref:`struct tst_test` members
|
||||
- Shell API ``$TST_*`` variables
|
||||
|
||||
* - .all_filesystems
|
||||
- TST_ALL_FILESYSTEMS
|
||||
|
||||
* - .bufs
|
||||
- \-
|
||||
|
||||
* - .caps
|
||||
- \-
|
||||
|
||||
* - .child_needs_reinit
|
||||
- not applicable
|
||||
|
||||
* - .cleanup
|
||||
- TST_CLEANUP
|
||||
|
||||
* - .dev_extra_opts
|
||||
- TST_DEV_EXTRA_OPTS
|
||||
|
||||
* - .dev_fs_opts
|
||||
- TST_DEV_FS_OPTS
|
||||
|
||||
* - .dev_fs_type
|
||||
- TST_FS_TYPE
|
||||
|
||||
* - .dev_min_size
|
||||
- TST_DEVICE_SIZE
|
||||
|
||||
* - .format_device
|
||||
- TST_FORMAT_DEVICE
|
||||
|
||||
* - .max_runtime
|
||||
- TST_TIMEOUT (not exactly the same, a real timeout based on old .timeout
|
||||
concept. .max_runtime has also an extra 30 sec safety margin for
|
||||
teardown of the test.)
|
||||
|
||||
* - .min_cpus
|
||||
- not applicable
|
||||
|
||||
* - .min_kver
|
||||
- TST_MIN_KVER
|
||||
|
||||
* - .min_mem_avail
|
||||
- not applicable
|
||||
|
||||
* - .mnt_flags
|
||||
- TST_MNT_PARAMS
|
||||
|
||||
* - .min_swap_avail
|
||||
- not applicable
|
||||
|
||||
* - .mntpoint | .mnt_data
|
||||
- TST_MNTPOINT
|
||||
|
||||
* - .mount_device
|
||||
- TST_MOUNT_DEVICE
|
||||
|
||||
* - .needs_cgroup_ctrls
|
||||
- \-
|
||||
|
||||
* - .needs_checkpoints
|
||||
- TST_NEEDS_CHECKPOINTS
|
||||
|
||||
* - .needs_cmds
|
||||
- TST_NEEDS_CMDS
|
||||
|
||||
* - .needs_devfs
|
||||
- \-
|
||||
|
||||
* - .needs_device
|
||||
- TST_NEEDS_DEVICE
|
||||
|
||||
* - .needs_drivers
|
||||
- TST_NEEDS_DRIVERS
|
||||
|
||||
* - .needs_kconfigs
|
||||
- TST_NEEDS_KCONFIGS
|
||||
|
||||
* - .needs_overlay
|
||||
- \-
|
||||
|
||||
* - .needs_rofs
|
||||
- \-
|
||||
|
||||
* - .needs_root
|
||||
- TST_NEEDS_ROOT
|
||||
|
||||
* - .needs_tmpdir
|
||||
- TST_NEEDS_TMPDIR
|
||||
|
||||
* - .options
|
||||
- TST_PARSE_ARGS | TST_OPTS
|
||||
|
||||
* - .resource_files
|
||||
- \-
|
||||
|
||||
* - .restore_wallclock
|
||||
- not applicable
|
||||
|
||||
* - .sample
|
||||
- \-
|
||||
|
||||
* - .save_restore
|
||||
- \-
|
||||
|
||||
* - .scall
|
||||
- not applicable
|
||||
|
||||
* - .setup
|
||||
- TST_SETUP
|
||||
|
||||
* - .skip_filesystems
|
||||
- TST_SKIP_FILESYSTEMS
|
||||
|
||||
* - .skip_in_compat
|
||||
- \-
|
||||
|
||||
* - .skip_in_lockdown
|
||||
- TST_SKIP_IN_LOCKDOWN
|
||||
|
||||
* - .skip_in_secureboot
|
||||
- TST_SKIP_IN_SECUREBOOT
|
||||
|
||||
* - .supported_archs
|
||||
- not applicable
|
||||
|
||||
* - .tags
|
||||
- \-
|
||||
|
||||
* - .taint_check
|
||||
- \-
|
||||
|
||||
* - .tcnt
|
||||
- TST_CNT
|
||||
|
||||
* - .tconf_msg
|
||||
- not applicable
|
||||
|
||||
* - .test | .test_all
|
||||
- TST_TESTFUNC
|
||||
|
||||
* - .test_variants
|
||||
- \-
|
||||
|
||||
* - .tst_hugepage
|
||||
- not applicable
|
||||
|
||||
* - .ulimit
|
||||
- not applicable
|
||||
|
||||
* - not applicable
|
||||
- TST_NEEDS_KCONFIGS_IFS
|
||||
|
||||
* - not applicable
|
||||
- TST_NEEDS_MODULE
|
||||
|
||||
* - not applicable
|
||||
- TST_POS_ARGS
|
||||
|
||||
* - not applicable
|
||||
- TST_USAGE
|
||||
|
||||
.. list-table::
|
||||
:header-rows: 1
|
||||
|
||||
* - C API other structs
|
||||
- Shell API ``$TST_*`` variables
|
||||
|
||||
* - :ref:`struct tst_device`
|
||||
- TST_DEVICE
|
||||
+112
@@ -0,0 +1,112 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
.. include:: ../README.rst
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 3
|
||||
:hidden:
|
||||
:caption: For users
|
||||
|
||||
users/quick_start
|
||||
users/setup_tests
|
||||
users/testers_guide
|
||||
users/supported_systems
|
||||
users/stats
|
||||
users/test_catalog
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 3
|
||||
:hidden:
|
||||
:caption: For developers
|
||||
|
||||
developers/setup_mailinglist
|
||||
developers/writing_tests
|
||||
developers/test_case_tutorial
|
||||
developers/api_c_tests
|
||||
developers/api_shell_tests
|
||||
developers/api_network_tests
|
||||
developers/api_kvm_tests
|
||||
developers/ltp_library
|
||||
developers/build_system
|
||||
developers/debugging
|
||||
developers/documentation
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 3
|
||||
:hidden:
|
||||
:caption: For maintainers
|
||||
|
||||
maintainers/patch_review
|
||||
maintainers/ltp_release_procedure
|
||||
|
||||
For users
|
||||
---------
|
||||
|
||||
.. descriptions here are active
|
||||
|
||||
:doc:`users/quick_start`
|
||||
How to build and use LTP framework in few steps
|
||||
|
||||
:doc:`users/setup_tests`
|
||||
How to setup tests execution
|
||||
|
||||
:doc:`users/supported_systems`
|
||||
A list of supported technologies by the LTP framework
|
||||
|
||||
:doc:`users/stats`
|
||||
Some LTP statistics
|
||||
|
||||
:doc:`users/test_catalog`
|
||||
The LTP test catalog
|
||||
|
||||
For developers
|
||||
--------------
|
||||
|
||||
.. descriptions here are active
|
||||
|
||||
:doc:`developers/setup_mailinglist`
|
||||
How to configure git and to start sending patches via :git_man:`send-email`.
|
||||
|
||||
:doc:`developers/writing_tests`
|
||||
Starting guide on writing tests
|
||||
|
||||
:doc:`developers/test_case_tutorial`
|
||||
A tutorial showing how to write a test from scratch using C API
|
||||
|
||||
:doc:`developers/api_c_tests`
|
||||
Walk through the C API features
|
||||
|
||||
:doc:`developers/api_shell_tests`
|
||||
Walk through the Shell API features
|
||||
|
||||
:doc:`developers/api_network_tests`
|
||||
Walk through the network API features
|
||||
|
||||
:doc:`developers/api_kvm_tests`
|
||||
Walk through the KVM API features
|
||||
|
||||
:doc:`developers/ltp_library`
|
||||
Developing new features in the LTP library
|
||||
|
||||
:doc:`developers/build_system`
|
||||
Short introduction to the LTP build system
|
||||
|
||||
:doc:`developers/debugging`
|
||||
How to debug LTP tests
|
||||
|
||||
:doc:`developers/documentation`
|
||||
How to use and develop LTP documentation
|
||||
|
||||
For maintainers
|
||||
---------------
|
||||
|
||||
:doc:`maintainers/patch_review`
|
||||
Steps to follow when reviewing patches
|
||||
|
||||
:doc:`maintainers/ltp_release_procedure`
|
||||
Steps to follow for a new LTP release
|
||||
|
||||
|
||||
Getting help
|
||||
------------
|
||||
To report a problem or suggest any feature, please write at ltp@lists.linux.it
|
||||
@@ -1,96 +0,0 @@
|
||||
The runtest files contain a list of test cases to be executed.
|
||||
|
||||
File Format
|
||||
-----------
|
||||
|
||||
Lines starting with a '#' are comments and blank lines are ignored.
|
||||
|
||||
Otherwise, lines start with a test name followed by white space, then some
|
||||
shell script to be executed. For example
|
||||
|
||||
Test Name
|
||||
| Delimiter Test case argument
|
||||
| | |
|
||||
v v v
|
||||
splice02 seq 1 20000 | splice02 splice02-temp
|
||||
^ ^ ^
|
||||
| | |
|
||||
| Test case executable |
|
||||
-----------Shell script-------------
|
||||
|
||||
So the splice02 runtest entry pipes the output of seq into the splice02 test
|
||||
executable. Most runtest entries are simpler than this, for example
|
||||
|
||||
splice03 splice03
|
||||
|
||||
Here the test name and executable have the same name and no arguments have
|
||||
been supplied.
|
||||
|
||||
Run test files should start with a comment describing the tests they contain,
|
||||
e.g.
|
||||
|
||||
#DESCRIPTION:Kernel system calls
|
||||
|
||||
Note that the LTP has absorbed a number of other projects. Some of these have
|
||||
been fully converted to the LTP format, others have runtest files generated
|
||||
for them during installation, while some use a shell script to integrate them
|
||||
with the other tests.
|
||||
|
||||
Test suites
|
||||
-----------
|
||||
|
||||
- syscalls (except epoll, see below)
|
||||
- fs
|
||||
- fsx
|
||||
- dio
|
||||
- mm
|
||||
- ipc
|
||||
- sched
|
||||
- math
|
||||
- pty
|
||||
|
||||
if run network tests flag is passed these additional tests are run
|
||||
- tcp_cmds
|
||||
- multicast
|
||||
- rpc
|
||||
- nfs
|
||||
|
||||
To test filesystem with LVM
|
||||
- testscripts/lvmtest.sh
|
||||
|
||||
Device Mapper tests
|
||||
- ltpdmmapper.sh
|
||||
|
||||
Network tests
|
||||
- network.sh
|
||||
- testcases/network/sockets/ltpSockets.sh
|
||||
|
||||
other filesystem or disk type tests
|
||||
- autofs1.sh
|
||||
- autofs4.sh
|
||||
- diskio.sh
|
||||
- isofs.sh
|
||||
- sysfs.sh
|
||||
|
||||
AIO/DIO filesystem tests
|
||||
- ltp-aiodio.sh
|
||||
|
||||
Device driver tests (may not run on all platforms)
|
||||
- acpi
|
||||
- agp
|
||||
- base
|
||||
- drm
|
||||
- include
|
||||
- nls
|
||||
- pci
|
||||
- tbio
|
||||
- usb
|
||||
|
||||
Open_hpi_testsuite
|
||||
- run_tests
|
||||
|
||||
Open_posix_testsuite
|
||||
- run_tests
|
||||
|
||||
|
||||
testcases/kernel/syscalls/epoll - The tests require additional installation files. See the README in the epoll directory.
|
||||
@@ -0,0 +1,166 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
Release process
|
||||
===============
|
||||
|
||||
Preparations
|
||||
------------
|
||||
|
||||
The release procedure generally takes a few weeks. In the first week or two,
|
||||
patches that should go into the release are reviewed and possibly merged. These
|
||||
patches are either fixes or patches pointed out by the community.
|
||||
|
||||
Patch review, when finished, is followed by a git freeze, which is a period
|
||||
where only fixes are pushed to the git. During that period community is
|
||||
expected to run a LTP pre-release tests, reports problems, and/or send fixes to
|
||||
the mailing list. In this period we are especially making sure that there are
|
||||
no regressions in the test results on a wide range of distributions and
|
||||
architectures.
|
||||
|
||||
Once the stabilization period has ended the time has finally come to proceed
|
||||
with the release.
|
||||
|
||||
Prepare the release notes
|
||||
-------------------------
|
||||
|
||||
Part of the preparation is also to write the release notes, which are then
|
||||
added to the GitHub release and also sent as announcement to various mailing
|
||||
lists (see below).
|
||||
|
||||
Have a look at `this release letter <https://lore.kernel.org/ltp/ZGNiQ1sMGvPU_ETp@yuki/>`_
|
||||
to get the idea how it should look.
|
||||
|
||||
Tag the git and push changes to github
|
||||
--------------------------------------
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
cd ltp
|
||||
echo YYYYMMDD > VERSION
|
||||
git commit -S -s -m 'LTP YYYYMMDD' VERSION
|
||||
git tag -s -a YYYYMMDD -m 'LTP YYYYMMDD'
|
||||
git push origin master:master
|
||||
git push origin YYYYMMDD
|
||||
|
||||
The string ``YYYYMMDD`` should be substituted to the current date.
|
||||
|
||||
You can use :master:`tools/tag-release.sh` script to have the above automated
|
||||
process. It allows you to verify the tag before pushing it and does other
|
||||
checks.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ ./tools/tag-release.sh
|
||||
===== git push =====
|
||||
new tag: 'YYYYMMDD', previous tag: '20230127'
|
||||
tag YYYYMMDD
|
||||
Tagger: Person-who-released LTP <foo@example.com>
|
||||
Date: ...
|
||||
|
||||
LTP YYYYMMDD
|
||||
-----BEGIN PGP SIGNATURE-----
|
||||
...
|
||||
-----END PGP SIGNATURE-----
|
||||
|
||||
commit 3ebc2dfa85c2445bb68d8c0d66e33c4da1e1b3a7
|
||||
gpg: using RSA key ...
|
||||
...
|
||||
Primary key fingerprint: ...
|
||||
Author: Person-who-released LTP <foo@example.com>
|
||||
Date: ...
|
||||
|
||||
LTP YYYYMMDD
|
||||
|
||||
Signed-off-by: Person-who-released LTP <foo@example.com>
|
||||
|
||||
diff --git a/VERSION b/VERSION
|
||||
index af4c41fec..ae488c0e7 100644
|
||||
--- a/VERSION
|
||||
+++ b/VERSION
|
||||
@@ -1 +1 @@
|
||||
-20230127
|
||||
+YYYYMMDD
|
||||
|
||||
Please check tag and signature. Proceed? [N/y]: y
|
||||
Pushing changes to upstream git. Proceed? [N/y]: y
|
||||
...
|
||||
To github.com:linux-test-project/ltp.git
|
||||
* [new tag] YYYYMMDD -> YYYYMMDD
|
||||
|
||||
Prepare tarballs and metadata documentation
|
||||
-------------------------------------------
|
||||
|
||||
The following procedure will show how to create the release archives and the
|
||||
metadata documentation:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
# clone already clonned git repository to new folder
|
||||
cd ..
|
||||
git clone ltp ltp-full-YYYYMMDD
|
||||
cd ltp-full-YYYYMMDD
|
||||
|
||||
# update all submodules
|
||||
git submodule update --init
|
||||
|
||||
# Generate configure script
|
||||
make autotools
|
||||
|
||||
# Generate tarballs
|
||||
cd ..
|
||||
tar -cjf ltp-full-YYYYMMDD.tar.bz2 ltp-full-YYYYMMDD --exclude .git
|
||||
tar -cJf ltp-full-YYYYMMDD.tar.xz ltp-full-YYYYMMDD --exclude .git
|
||||
|
||||
# Generate checksums
|
||||
md5 ltp-full-YYYYMMDD.tar.xz > ltp-full-YYYYMMDD.tar.xz.md5
|
||||
sha1 ltp-full-YYYYMMDD.tar.xz > ltp-full-YYYYMMDD.tar.xz.sha1
|
||||
sha256sum ltp-full-YYYYMMDD.tar.xz > ltp-full-YYYYMMDD.tar.xz.sha256
|
||||
|
||||
You can use :master:`tools/create-tarballs-metadata.sh` script to have the above
|
||||
procedure automated. All generated files are placed in the
|
||||
``ltp-release-YYYYMMDD`` directory.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ ./tools/create-tarballs-metadata.sh
|
||||
===== git clone =====
|
||||
Cloning into 'ltp-full-YYYYMMDD'...
|
||||
done.
|
||||
===== Update submodules =====
|
||||
Submodule 'tools/kirk' (https://github.com/linux-test-project/kirk.git) registered for path 'tools/kirk'
|
||||
...
|
||||
===== Generate configure script =====
|
||||
sed -n '1{s:LTP-:m4_define([LTP_VERSION],[:;s:$:]):;p;q}' VERSION > m4/ltp-version.m4
|
||||
aclocal -I m4
|
||||
...
|
||||
===== Generate tarballs =====
|
||||
===== Generate checksums =====
|
||||
===== Generate metadata documentation =====
|
||||
checking for a BSD-compatible install... /usr/bin/install -c
|
||||
...
|
||||
Generated files are in '/home/foo/ltp-release-YYYYMMDD', upload them to github
|
||||
|
||||
Upload the generated files to GitHub
|
||||
------------------------------------
|
||||
|
||||
Go to :repo:`tags`. Click on ``Add release notes``.
|
||||
There should be ``Attach binaries ...`` link at the bottom of the page.
|
||||
|
||||
Don't forget to upload checksums for the tarballs and metadata documentation
|
||||
as well.
|
||||
|
||||
Send release announcement
|
||||
-------------------------
|
||||
|
||||
The announcement is sent to:
|
||||
|
||||
* ltp at lists.linux.it (requires a subscription)
|
||||
* linux-kernel at vger.kernel.org
|
||||
* libc-alpha at sourceware.org (requires a subscription)
|
||||
* valgrind-developers at lists.sourceforge.net (requires a subscription)
|
||||
|
||||
CCed to:
|
||||
|
||||
* lwn at lwn.net
|
||||
* akpm at linux-foundation.org
|
||||
* torvalds at linux-foundation.org
|
||||
@@ -0,0 +1,167 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
Patch review
|
||||
============
|
||||
|
||||
Anyone can and should review patches. It's the only way to get good at patch
|
||||
review and for the project to scale. For this reason, we have a short guide on
|
||||
what to do during the review process.
|
||||
|
||||
Goals of patch review
|
||||
---------------------
|
||||
|
||||
#. Prevent false positive test results
|
||||
#. Prevent false negative test results
|
||||
#. Keep the code as simple as possible, but no simpler
|
||||
|
||||
How to find clear errors
|
||||
------------------------
|
||||
|
||||
A clear error is one where there is unlikely to be any argument if you
|
||||
provide evidence of it. Evidence being an error trace or logical proof
|
||||
that an error will occur in a common situation.
|
||||
|
||||
The following are examples and may not be appropriate for all tests.
|
||||
|
||||
* Merge the patch locally. It should apply cleanly to master.
|
||||
* Compile the patch with default and non-default configurations.
|
||||
|
||||
* Use sanitizers e.g. undefined behavior, address.
|
||||
* Compile on non-x86
|
||||
* Compile on x86 with ``-m32``
|
||||
* Compile testing patches with GitHub Actions in LTP repo fork can cover
|
||||
various distros/architectures
|
||||
|
||||
* Use ``make check``
|
||||
* Run effected tests in a VM
|
||||
|
||||
* Use single vCPU
|
||||
* Use many vCPUs and enable NUMA
|
||||
* Restrict RAM to < 1GB.
|
||||
|
||||
* Run effected tests on an embedded device
|
||||
* Run effected tests on non-x86 machine in general
|
||||
* Run reproducers on a kernel where the bug is present
|
||||
* Run tests with ``-i0`` and ``-i2``
|
||||
* Compare usage of system calls with man page descriptions
|
||||
* Compare usage of system calls with kernel code
|
||||
* Double check commit message
|
||||
* Search the LTP library for existing helper functions
|
||||
* Check doc formatting, see :doc:`../developers/documentation`.
|
||||
|
||||
How to find subtle errors
|
||||
-------------------------
|
||||
|
||||
A subtle error is one where you can expect some argument because you
|
||||
do not have clear evidence of an error. It is best to state these as
|
||||
questions and not make assertions if possible.
|
||||
|
||||
Although if it is a matter of style or "taste" then senior maintainers
|
||||
can assert what is correct to avoid bike shedding.
|
||||
|
||||
* Ask what happens if there is an error, could it be debugged just
|
||||
with the test output?
|
||||
* Are we testing undefined behavior?
|
||||
|
||||
* Could future kernel behavior change without "breaking userland"?
|
||||
* Does the kernel behave differently depending on hardware?
|
||||
* Does it behave differently depending on kernel configuration?
|
||||
* Does it behave differently depending on the compiler?
|
||||
* Would it behave differently if the order of checks on syscall parameters
|
||||
changed in the kernel?
|
||||
|
||||
* Will it scale to tiny and huge systems?
|
||||
|
||||
* What happens if there are 100+ CPUs?
|
||||
* What happens if each CPU core is very slow?
|
||||
* What happens if there are 2TB of RAM?
|
||||
|
||||
* Are we repeating a pattern that can be turned into a library function?
|
||||
* Is a single test trying to do too much?
|
||||
* Could multiple similar tests be merged?
|
||||
* Race conditions
|
||||
|
||||
* What happens if a process gets preempted?
|
||||
* Could checkpoints or fuzzsync by used instead?
|
||||
* Note, usually you can insert a sleep to prove a race condition
|
||||
exists however finding them is hard
|
||||
|
||||
* Is there a simpler way to achieve the same kernel coverage?
|
||||
|
||||
How to get patches merged
|
||||
-------------------------
|
||||
|
||||
Once you think a patch is good enough you should add your ``Reviewed-by``
|
||||
and/or ``Tested-by`` tags. This means you will get some credit for getting
|
||||
the patch merged. Also some blame if there are problems.
|
||||
|
||||
If you ran the test you can add the ``Tested-by`` tag. If you read the
|
||||
code or used static analysis tools on it, you can add the Reviewed-by
|
||||
tag.
|
||||
|
||||
In addition you can expect others to review your patches and add their
|
||||
tags. This will speed up the process of getting your patches merged.
|
||||
|
||||
Maintainers Checklist
|
||||
---------------------
|
||||
|
||||
Patchset should be tested locally and ideally also in maintainer's fork in
|
||||
GitHub Actions on GitHub.
|
||||
|
||||
.. note::
|
||||
|
||||
GitHub Actions do only build testing, passing the CI means only that
|
||||
the test compiles fine on variety of different distributions and releases.
|
||||
|
||||
The test should be executed at least once locally and should PASS as well.
|
||||
|
||||
Commit messages should have
|
||||
|
||||
* Author's ``Signed-off-by`` tag
|
||||
* Committer's ``Reviewed-by`` or ``Signed-off-by`` tag
|
||||
* Check also mailing lists for other reviewers / testers tags, notes and failure
|
||||
reports
|
||||
* ``Fixes: hash`` if it fixes particular LTP commit
|
||||
* ``Fixes: #N`` if it fixes github issue number N, so it's automatically closed
|
||||
* LTP documentation should be kept up to date.
|
||||
|
||||
After patch is accepted or rejected, set correct state and archive in the
|
||||
`LTP patchwork instance <https://patchwork.ozlabs.org/project/ltp/list/>`_.
|
||||
|
||||
New tests
|
||||
---------
|
||||
|
||||
New test should
|
||||
|
||||
* Have a record in runtest file
|
||||
* Test should work fine with more than one iteration (e.g. run with ``-i 100``)
|
||||
* Run with ``-i 0`` to check that setup and cleanup are coded properly
|
||||
(no test is being run)
|
||||
* Have a brief description
|
||||
* License: the default license for new tests is GPL v2 or later, use
|
||||
``GPL-2.0-or-later``; the license for test (e.g. GPL-2.0) should not change
|
||||
unless test is completely rewritten
|
||||
* Old copyrights should be kept unless test is completely rewritten
|
||||
|
||||
C tests
|
||||
~~~~~~~
|
||||
|
||||
* Use :doc:`../developers/api_c_tests`, implementing :ref:`struct tst_test`
|
||||
* Test binaries are added into corresponding ``.gitignore`` files
|
||||
* Check coding style with ``make check``
|
||||
* Metadata documentation
|
||||
* If a test is a regression test it should include :ref:`.tags<struct tst_tag>` in the
|
||||
:ref:`struct tst_test` definition
|
||||
|
||||
Shell tests
|
||||
~~~~~~~~~~~
|
||||
|
||||
* Use :doc:`../developers/api_shell_tests`
|
||||
* Check coding style with ``make check``
|
||||
* If a test is a regression test it should include related kernel or glibc
|
||||
commits as a comment
|
||||
|
||||
LTP library
|
||||
~~~~~~~~~~~
|
||||
|
||||
For patchset touching the LTP library, follow :doc:`../developers/ltp_library`.
|
||||
@@ -1,27 +0,0 @@
|
||||
#
|
||||
# man1 Makefile.
|
||||
#
|
||||
# Copyright (C) 2009, Cisco Systems Inc.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along
|
||||
# with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
#
|
||||
# Ngie Cooper, July 2009
|
||||
#
|
||||
|
||||
MANPREFIX := 1
|
||||
|
||||
top_srcdir ?= ../..
|
||||
|
||||
include $(top_srcdir)/include/mk/man.mk
|
||||
@@ -1,70 +0,0 @@
|
||||
.\"
|
||||
.\" $Id: doio.1,v 1.1 2000/07/27 16:59:03 alaffin Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved.
|
||||
.\"
|
||||
.\" This program is free software; you can redistribute it and/or modify it
|
||||
.\" under the terms of version 2 of the GNU General Public License as
|
||||
.\" published by the Free Software Foundation.
|
||||
.\"
|
||||
.\" This program is distributed in the hope that it would be useful, but
|
||||
.\" WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
.\"
|
||||
.\" Further, this software is distributed without any warranty that it is
|
||||
.\" free of the rightful claim of any third person regarding infringement
|
||||
.\" or the like. Any license provided herein, whether implied or
|
||||
.\" otherwise, applies only to this software file. Patent licenses, if
|
||||
.\" any, provided herein do not apply to combinations of this program with
|
||||
.\" other software, or any other product whatsoever.
|
||||
.\"
|
||||
.\" You should have received a copy of the GNU General Public License along
|
||||
.\" with this program; if not, write the Free Software Foundation, Inc.,
|
||||
.\" 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
.\"
|
||||
.\" Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
|
||||
.\" Mountain View, CA 94043, or:
|
||||
.\"
|
||||
.\" http://www.sgi.com
|
||||
.\"
|
||||
.\" For further information regarding this notice, see:
|
||||
.\"
|
||||
.\" http://oss.sgi.com/projects/GenInfo/NoticeExplan/
|
||||
.\"
|
||||
.TH doio 1 10/13/93 "UNICOS Testing"
|
||||
.SH NAME
|
||||
\*Cdoio\fR - Executes I/O Requests
|
||||
.SH IMPLEMENTATION
|
||||
All Cray Research systems
|
||||
.SH SYNOPSIS
|
||||
\*Cdoio\fR
|
||||
.SH DESCRIPTION
|
||||
.QS
|
||||
Doio is one of the device-beater tools.
|
||||
.PP
|
||||
Options:
|
||||
.RS .5i
|
||||
.IP "-a"
|
||||
abort on data compare errors
|
||||
.IP "-n opt"
|
||||
.IP "-k opt"
|
||||
lockd request pipe
|
||||
.IP "-K opt"
|
||||
use fcntl() file locking
|
||||
.IP "-r opt"
|
||||
resource release interval
|
||||
.IP "-s opt"
|
||||
syscall log file
|
||||
.IP "-w opt"
|
||||
file write log file
|
||||
.IP "-v"
|
||||
verify writes if set
|
||||
.IP "-U opt"
|
||||
upanic() on varios conditions
|
||||
.RE
|
||||
.SH AUTHOR
|
||||
Mark Maule wrote the code.
|
||||
.br
|
||||
Glen Overby wrote the man page.
|
||||
.SH BUGS
|
||||
See "Features".
|
||||
@@ -1,78 +0,0 @@
|
||||
.\"
|
||||
.\" $Id: iogen.1,v 1.1 2000/07/27 16:59:03 alaffin Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved.
|
||||
.\"
|
||||
.\" This program is free software; you can redistribute it and/or modify it
|
||||
.\" under the terms of version 2 of the GNU General Public License as
|
||||
.\" published by the Free Software Foundation.
|
||||
.\"
|
||||
.\" This program is distributed in the hope that it would be useful, but
|
||||
.\" WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
.\"
|
||||
.\" Further, this software is distributed without any warranty that it is
|
||||
.\" free of the rightful claim of any third person regarding infringement
|
||||
.\" or the like. Any license provided herein, whether implied or
|
||||
.\" otherwise, applies only to this software file. Patent licenses, if
|
||||
.\" any, provided herein do not apply to combinations of this program with
|
||||
.\" other software, or any other product whatsoever.
|
||||
.\"
|
||||
.\" You should have received a copy of the GNU General Public License along
|
||||
.\" with this program; if not, write the Free Software Foundation, Inc.,
|
||||
.\" 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
.\"
|
||||
.\" Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
|
||||
.\" Mountain View, CA 94043, or:
|
||||
.\"
|
||||
.\" http://www.sgi.com
|
||||
.\"
|
||||
.\" For further information regarding this notice, see:
|
||||
.\"
|
||||
.\" http://oss.sgi.com/projects/GenInfo/NoticeExplan/
|
||||
.\"
|
||||
.TH iogen 1 10/13/93 "UNICOS Testing"
|
||||
.SH NAME
|
||||
\*Ciogen\fR - Generate I/O Requests
|
||||
.SH IMPLEMENTATION
|
||||
All Cray Research systems
|
||||
.SH SYNOPSIS
|
||||
\*Ciogen\fR
|
||||
.SH DESCRIPTION
|
||||
.QS
|
||||
Iogen is one of the device-beater tools.
|
||||
.PP
|
||||
Options:
|
||||
.RS .5i
|
||||
.IP "-f [opt]"
|
||||
open flags:
|
||||
raw, sync, ssd, ldraw, buffered
|
||||
.IP "-i [opt]"
|
||||
Number of iterations to run.
|
||||
0 implies infinite.
|
||||
.IP "-q"
|
||||
.IP "-m [opt]"
|
||||
Offset mode.
|
||||
One of: random, sequential, reverse.
|
||||
.IP "-o"
|
||||
Overlap flag.
|
||||
.IP "-p [opt]"
|
||||
output pipe (default is stdout)
|
||||
.IP "-r [opt]"
|
||||
specify raw io multiple instead of getting it from the mounted on device.
|
||||
Only applies to regular files.
|
||||
.IP "-s [opt]"
|
||||
System calls to use for I/O.
|
||||
A list of:
|
||||
read, write, reada, writea, ssread, sswrite
|
||||
.IP "-t [opt]"
|
||||
min transfer size
|
||||
.IP "-T [opt]"
|
||||
max transfer size
|
||||
.RE
|
||||
.SH AUTHOR
|
||||
Mark Maule wrote the code.
|
||||
.br
|
||||
Glen Overby wrote the man page.
|
||||
.SH BUGS
|
||||
See "Features".
|
||||
@@ -1,80 +0,0 @@
|
||||
.\"
|
||||
.\" $Id: ltp-bump.1,v 1.1 2009/05/19 09:39:11 subrata_modak Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved.
|
||||
.\"
|
||||
.\" This program is free software; you can redistribute it and/or modify it
|
||||
.\" under the terms of version 2 of the GNU General Public License as
|
||||
.\" published by the Free Software Foundation.
|
||||
.\"
|
||||
.\" This program is distributed in the hope that it would be useful, but
|
||||
.\" WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
.\"
|
||||
.\" Further, this software is distributed without any warranty that it is
|
||||
.\" free of the rightful claim of any third person regarding infringement
|
||||
.\" or the like. Any license provided herein, whether implied or
|
||||
.\" otherwise, applies only to this software file. Patent licenses, if
|
||||
.\" any, provided herein do not apply to combinations of this program with
|
||||
.\" other software, or any other product whatsoever.
|
||||
.\"
|
||||
.\" You should have received a copy of the GNU General Public License along
|
||||
.\" with this program; if not, write the Free Software Foundation, Inc.,
|
||||
.\" 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
.\"
|
||||
.\" Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
|
||||
.\" Mountain View, CA 94043, or:
|
||||
.\"
|
||||
.\" http://www.sgi.com
|
||||
.\"
|
||||
.\" For further information regarding this notice, see:
|
||||
.\"
|
||||
.\" http://oss.sgi.com/projects/GenInfo/NoticeExplan/
|
||||
.\"
|
||||
.TH BUMP 1 "14 Sep 2000" "LTP" "Linux Test Project"
|
||||
.SH NAME
|
||||
ltp-bump \- send signal to tags run by ltp-pan
|
||||
.SH SYNOPSIS
|
||||
\fBltp-bump [-1] [-s \fIsig\fB] [\fI-a active-file\fB] [tags...]
|
||||
.SH DESCRIPTION
|
||||
|
||||
Bump will send a SIGINT signal to processes, given that each process has a
|
||||
corresponding tag in an active-file. The active-file is the same one that is
|
||||
used by the ltp-pan to start the processes.
|
||||
|
||||
If the active file has multiple occurrences of a single tag name then only the
|
||||
first process will be signaled. You may specify the tag name multiple times
|
||||
on the commandline if necessary.
|
||||
|
||||
.TP 1i
|
||||
\fB-1\fP
|
||||
Send a SIGUSR1 signal. By default a SIGINT will be sent.
|
||||
.TP 1i
|
||||
\fB-a \fIactive_file\fB
|
||||
A file containing the tagnames, pids, and commands being run by a ltp-pan. If this
|
||||
is not specified then the ZOO environment variable will be read for the name of
|
||||
the directory where the active file can be found.
|
||||
.TP 1i
|
||||
\fB-s \fIsig\fB
|
||||
Used to specify a signal number to send. By default a SIGINT will be sent.
|
||||
|
||||
.in -1i
|
||||
|
||||
.SH ENVIRONMENT
|
||||
.TP
|
||||
ZOO
|
||||
If set, should name the directory where the active file can be found.
|
||||
This is ignored if \fI-a\fP is specified.
|
||||
|
||||
.SH FILES
|
||||
.TP
|
||||
active
|
||||
Default name of active file if \fI-a\fP is not specified. This is prefixed
|
||||
by the directory name found in the ZOO environment variable.
|
||||
|
||||
.SH "SEE ALSO"
|
||||
Zoo tools - ltp-pan(1)
|
||||
|
||||
.SH DIAGNOSTICS
|
||||
Exits zero, unless it cannot find the active file or if there were no tags
|
||||
listed on the commandline.
|
||||
@@ -1,262 +0,0 @@
|
||||
.\"
|
||||
.\" $Id: ltp-pan.1,v 1.1 2009/05/19 09:39:11 subrata_modak Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved.
|
||||
.\"
|
||||
.\" This program is free software; you can redistribute it and/or modify it
|
||||
.\" under the terms of version 2 of the GNU General Public License as
|
||||
.\" published by the Free Software Foundation.
|
||||
.\"
|
||||
.\" This program is distributed in the hope that it would be useful, but
|
||||
.\" WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
.\"
|
||||
.\" Further, this software is distributed without any warranty that it is
|
||||
.\" free of the rightful claim of any third person regarding infringement
|
||||
.\" or the like. Any license provided herein, whether implied or
|
||||
.\" otherwise, applies only to this software file. Patent licenses, if
|
||||
.\" any, provided herein do not apply to combinations of this program with
|
||||
.\" other software, or any other product whatsoever.
|
||||
.\"
|
||||
.\" You should have received a copy of the GNU General Public License along
|
||||
.\" with this program; if not, write the Free Software Foundation, Inc.,
|
||||
.\" 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
.\"
|
||||
.\" Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
|
||||
.\" Mountain View, CA 94043, or:
|
||||
.\"
|
||||
.\" http://www.sgi.com
|
||||
.\"
|
||||
.\" For further information regarding this notice, see:
|
||||
.\"
|
||||
.\" http://oss.sgi.com/projects/GenInfo/NoticeExplan/
|
||||
.TH PAN 1 "21 Jan 2011" "LTP" "Linux Test Project"
|
||||
.SH NAME
|
||||
ltp-pan \- A light-weight driver to run tests and clean up their pgrps
|
||||
.SH SYNOPSIS
|
||||
\fBltp-pan -n tagname [-SyAehp] [-t #s|m|h|d \fItime\fB] [-s \fIstarts\fB] [\fI-x nactive\fB] [\fI-l logfile\fB] [\fI-a active-file\fB] [\fI-f command-file\fB] [\fI-d debug-level\fB] [\fI-o output-file\fB] [\fI-O buffer_directory\fB] [\fI-r report_type\fB] [\fI-C fail-command-file\fB] [cmd]
|
||||
.SH DESCRIPTION
|
||||
|
||||
Pan will run a command, as specified on the commandline, or collection of
|
||||
commands from a command-file. By default ltp-pan runs one command, choosing it at
|
||||
random from the whole set of commands available to it. The ltp-pan's name in the
|
||||
active file is specified by the tagname. When a command terminates ltp-pan will
|
||||
kill any orphans that may have been left behind in its pgrp. If ltp-pan is
|
||||
signaled it will kill any active commands and, again, clean up any orphans.
|
||||
|
||||
Pan uses the signal ratchet found in other zoo tools. The first time ltp-pan is
|
||||
signaled it sends a SIGTERM to the active pgrps; the second time it sends
|
||||
SIGHUP; the third time a SIGINT; after that it always sends SIGKILL.
|
||||
|
||||
Pan will not terminate until all the active commands and everything in their
|
||||
pgrps is dead. It will loop around at 5 second intervals, triggering its own
|
||||
signal ratchet, until it succeeds in killing the pgrps.
|
||||
|
||||
When the ltp-pan starts up it places its own tagname and commandline in the active
|
||||
file and begins scheduling commands. After a command is started ltp-pan puts an
|
||||
entry for it into the active file with its indicated tagname. If the command
|
||||
was specified on the command line, rather than in the command-file, then its
|
||||
tagname will be "cmdln". When a process terminates ltp-pan frees the active file
|
||||
entry. If a command terminates and leaves an orphaned pgrp then ltp-pan will put
|
||||
an entry into the active file called "panorphan" which will be removed only
|
||||
when the orphaned pgrp is cleaned up. Before ltp-pan exits it will ensure that
|
||||
all orphaned pgrps are dead (see above) and then it will remove its own
|
||||
tagname from the active file.
|
||||
|
||||
The command-file is a file containing tag/command pairs. Each line in the
|
||||
file begins with a tag identifying the command, followed by white space, and
|
||||
then the command and its arguments. A line beginning with the # character is
|
||||
a comment. Pan recognizes the token "%f" in a command's arguments and
|
||||
replaces it with a unique identifier--add this to filename arguments to
|
||||
prevent two instances of the command from interfering with each other.
|
||||
|
||||
When ltp-pan receives a SIGUSR2 it stops scheduling new tests and waits for the
|
||||
active tests to terminate. If the \fB-y\fP option was used then it will begin
|
||||
scheduling again, otherwise it will exit. It does not propagate the SIGUSR2.
|
||||
|
||||
.TP 1i
|
||||
\fB-A\fP
|
||||
The all-stop flag. If any command exits non-zero ltp-pan will shutdown its
|
||||
scheduler and signal any active pgrps. The ltp-pan will exit non-zero after
|
||||
everything is shut down. By default ltp-pan ignores command exit statuses.
|
||||
The \fI-e\fP option is implied when this option is used.
|
||||
.TP 1i
|
||||
\fB-a \fIactive_file\fB
|
||||
A file containing the tagnames, pids, and commands being run. If this is
|
||||
not specified then the ZOO environment variable will be read for the name
|
||||
of a directory where the active file will be placed, and in this case the
|
||||
active file's name will be "active". A single active file may be shared
|
||||
by any number of Zoo tools.
|
||||
.TP 1i
|
||||
\fB-C \fIfail-command-file\fB
|
||||
The file to which all failed test commands will be saved. You can use it later with \fI-f\fP option if you want to run only the failed test cases.
|
||||
.TP 1i
|
||||
\fB-d \fIdebug-level\fB
|
||||
See the source for settings.
|
||||
.TP 1i
|
||||
\fB-e\fP
|
||||
Pan will exit non-zero if any of its commands exited non-zero. By default
|
||||
ltp-pan ignores command exit statuses.
|
||||
.TP 1i
|
||||
\fB-f \fIcommand-file\fB
|
||||
The file that has a collection of commands that ltp-pan will execute.
|
||||
.TP 1i
|
||||
\fB-h\fP
|
||||
Print some simple help.
|
||||
.TP 1i
|
||||
\fB-l \fIlogfile\fB
|
||||
Name of a log file to be used to store exit information for each of the
|
||||
commands (tags) that are run. This log file may not be shared with other Zoo
|
||||
tools or other ltp-pan processes.
|
||||
.TP 1i
|
||||
\fB-n \fItagname\fB
|
||||
The tagname by which this ltp-pan process will be known by the zoo tools. This
|
||||
is a required argument.
|
||||
.TP 1i
|
||||
\fB-o \fIoutput_file\fB
|
||||
The file to which all test output will be saved. Normally all test output is sent to standard output. This includes each test's standard output and standard error.
|
||||
.TP 1i
|
||||
\fB-O \fIbuffer_directory\fB
|
||||
A directory where ltp-pan can place temporary files to capture test output. This will prevent output from several tests mixing together in the output file.
|
||||
.TP 1i
|
||||
\fB-p\fP
|
||||
Enables printing results in human readable format.
|
||||
.TP 1i
|
||||
\fB-r \fIreport_type\fB
|
||||
This controls the type of output that ltp-pan will produce. Supported formats are \fIrts\fP and \fInone\fP. The default is \fIrts\fP.
|
||||
.TP 1i
|
||||
\fB-S\fP
|
||||
Causes ltp-pan to run commands (tags) sequentially, as they are listed in the
|
||||
command-file. By default it chooses tags randomly. If a command is specified
|
||||
on the commandline and a command-file is also specified, then the commandline
|
||||
tag will be the last command. If this is specified and \fI-s\fP is not
|
||||
specified then the default setting for \fI-s\fP is equal to the total number
|
||||
of commands.
|
||||
.TP 1i
|
||||
\fB-s \fIstarts\fB
|
||||
Indicates the number of commands (tags) that should be run before terminating.
|
||||
Set this to zero to run forever. By default this is set to 1 (but see
|
||||
\fI-S\fP for an exception). If this is specified and is less than the value
|
||||
specified for \fI-x\fP then it is bumped up to be equal to the value of
|
||||
\fI-x\fP (in other words, \fI-x\fP is always satisfied).
|
||||
.TP 1i
|
||||
\fB-t #s|m|h|d \fItime\fB
|
||||
Indicates the length that ltp-pan should run tests. By default this is not set. If specified,
|
||||
the \fI-s\fP flag is automatically set to 0 (infinite). Presumably, you want as many
|
||||
tests ran during this timeframe. Duration is measured in \fIs\fPeconds, \fIm\fPinutes,
|
||||
\fIh\fPours, or \fId\fPays.
|
||||
.TP 1i
|
||||
\fB-x \fInactive\fB
|
||||
Indicates the number of commands (tags) that should be kept active at any one
|
||||
time. If this is greater than 1 then it is possible to have multiple
|
||||
instances of the same tag active at once. By default this is 1.
|
||||
.TP 1i
|
||||
\fB-y\fP
|
||||
Causes the ltp-pan scheduler to go idle if a signal is received or if a command
|
||||
exits non-zero. All active commands and their pgrps will be killed. After
|
||||
everything is dead the scheduler will restart again where it left off. If the
|
||||
signal is SIGUSR1 then ltp-pan will behave as if \fI-y\fP had not been specified.
|
||||
|
||||
.in -1i
|
||||
|
||||
.SH EXAMPLES
|
||||
|
||||
In practice, the ZOO environment variable is generally preferred over the
|
||||
\fI-a\fP option. All examples assume this is being set.
|
||||
|
||||
The following creates a ltp-pan named "ex1" with an active file in /tmp/active.
|
||||
It runs the command "echo hello", keeping 3 copies running at all times,
|
||||
running 10 copies before terminating.
|
||||
|
||||
$ export ZOO=/tmp
|
||||
.br
|
||||
$ ltp-pan -n ex1 -s 10 -x 3 echo hello
|
||||
|
||||
The next example will use this command file. Call this /tmp/cmds1.
|
||||
.br
|
||||
----------cut------
|
||||
.br
|
||||
fido ls /bin
|
||||
.br
|
||||
rover echo hello wally
|
||||
.br
|
||||
gidget sleep 2
|
||||
.br
|
||||
lassie ls /etc
|
||||
.br
|
||||
----------cut------
|
||||
.br
|
||||
|
||||
Using the above command file, /tmp/cmds1, run one command at a time,
|
||||
sequentially, running each command only once. If one command should fail then
|
||||
terminate immediately. An exit log is kept for all the commands.
|
||||
|
||||
$ ltp-pan -n ex3 -S -A -f /tmp/cmds1 -l ex3.log
|
||||
|
||||
Here is just a simple stress case. In this case the test will run for 24 hours,
|
||||
printing the output as a human readable format, with the test output at /tmp/output-file
|
||||
and all failed test commands (if you have any) at /tmp/fail-command-file.
|
||||
|
||||
$ ltp-pan -n stress -e -p -q -S -t 24h -a stress -l logfile -f command-file \
|
||||
-o /tmp/output-file -C /tmp/fail-command-file
|
||||
|
||||
.SH LAYERING
|
||||
|
||||
Pan is often used in layers. This section extends the above examples to show
|
||||
how this is done.
|
||||
|
||||
The next example will use this command file. Call this /tmp/cmds2. Note that
|
||||
the embedded ltp-pans inside this file have exit logs, and that %f is used to give
|
||||
each ltp-pan a unique log file name.
|
||||
.br
|
||||
----------cut------
|
||||
.br
|
||||
larry ltp-pan -n ex4b -s10 -A -l ex4_%f.log echo hello
|
||||
.br
|
||||
curly ltp-pan -n ex4c -S -A -f /tmp/cmds1 -l ex4_%f.log
|
||||
.br
|
||||
moe echo done here
|
||||
.br
|
||||
----------cut------
|
||||
.br
|
||||
|
||||
The following will run commands from the command file, keeping two at a time
|
||||
running, choosing them sequentially, and terminating if any of them exits
|
||||
non-zero.
|
||||
|
||||
$ ltp-pan -n ex4 -x2 -A -S -f /tmp/cmds2
|
||||
|
||||
Now run the commands in /tmp/cmds2, but this time we want to recover if one of
|
||||
the commands should exit non-zero. In this example it is possible for the
|
||||
"larry" or "curly" tags to exit non-zero. When this happens the ltp-pan will kill
|
||||
all active tags, making sure both larry and curly are dead, and then will
|
||||
continue scheduling--ensuring that our "done here" message comes out no matter
|
||||
what.
|
||||
|
||||
$ ltp-pan -n ex5 -x2 -A -S -y -f /tmp/cmds2
|
||||
|
||||
.SH ENVIRONMENT
|
||||
.TP
|
||||
ZOO
|
||||
If set, should name the directory where the active file should be placed.
|
||||
This is ignored if \fI-a\fP is specified.
|
||||
|
||||
.SH FILES
|
||||
.TP
|
||||
active
|
||||
Default name of active file if \fI-a\fP is not specified. This is prefixed
|
||||
by the directory name found in the ZOO environment variable.
|
||||
.TP
|
||||
PAN_STOP_FILE
|
||||
The creation of this file in the defined \fITMP\fP directory will cause ltp-pan to
|
||||
execute one more loop and stop. This is useful when testing needs to be stopped
|
||||
before its scheduled stop time (\fI-t\fP). By doing a 'touch' on this file, testing
|
||||
is ended, i.e. touch /tmp/runalltests-2345/PAN_STOP_FILE
|
||||
|
||||
.SH "SEE ALSO"
|
||||
Zoo tools - ltp-bump(1)
|
||||
|
||||
.SH DIAGNOSTICS
|
||||
By default it exits zero unless signaled, regardless of the exit status of any
|
||||
of the commands it is running. If \fI-A\fP or \fI-e\fP are specified it exits non-zero if
|
||||
it is signaled or if any of the commands it is running should exit non-zero.
|
||||
@@ -1,27 +0,0 @@
|
||||
#
|
||||
# man3 Makefile.
|
||||
#
|
||||
# Copyright (C) 2009, Cisco Systems Inc.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along
|
||||
# with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
#
|
||||
# Ngie Cooper, July 2009
|
||||
#
|
||||
|
||||
MANPREFIX := 3
|
||||
|
||||
top_srcdir ?= ../..
|
||||
|
||||
include $(top_srcdir)/include/mk/man.mk
|
||||
@@ -1,179 +0,0 @@
|
||||
.\"
|
||||
.\" $Id: parse_opts.3,v 1.3 2000/08/31 18:40:28 nstraz Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved.
|
||||
.\"
|
||||
.\" This program is free software; you can redistribute it and/or modify it
|
||||
.\" under the terms of version 2 of the GNU General Public License as
|
||||
.\" published by the Free Software Foundation.
|
||||
.\"
|
||||
.\" This program is distributed in the hope that it would be useful, but
|
||||
.\" WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
.\"
|
||||
.\" Further, this software is distributed without any warranty that it is
|
||||
.\" free of the rightful claim of any third person regarding infringement
|
||||
.\" or the like. Any license provided herein, whether implied or
|
||||
.\" otherwise, applies only to this software file. Patent licenses, if
|
||||
.\" any, provided herein do not apply to combinations of this program with
|
||||
.\" other software, or any other product whatsoever.
|
||||
.\"
|
||||
.\" You should have received a copy of the GNU General Public License along
|
||||
.\" with this program; if not, write the Free Software Foundation, Inc.,
|
||||
.\" 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
.\"
|
||||
.\" Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
|
||||
.\" Mountain View, CA 94043, or:
|
||||
.\"
|
||||
.\" http://www.sgi.com
|
||||
.\"
|
||||
.\" For further information regarding this notice, see:
|
||||
.\"
|
||||
.\" http://oss.sgi.com/projects/GenInfo/NoticeExplan/
|
||||
.\"
|
||||
.TH PARSE_OPTS 3 "21 Jan 2011" "LTP" "Linux Test Project"
|
||||
.SH NAME
|
||||
parse_opts \- parse standard and user options for LTP test programs
|
||||
.SH SYNOPSIS
|
||||
.nf
|
||||
.B #include \(rqtest.h\(rq
|
||||
.B #include \(rqusctest.h\(rq
|
||||
.sp
|
||||
.BI "char *parse_opts(int " argc ", char *" argv[] ", "
|
||||
.BI " option_t " option_array[] ","
|
||||
.BI " void (*" user_help_func ")());"
|
||||
.fi
|
||||
.SH DESCRIPTION
|
||||
The \fBparse_opts()\fP routine parses options from the command line, looking
|
||||
for user specified options or standard options (see below). Its arguments
|
||||
\fIargc\fP and \fIargv\fP are the argument count and array as passed to the
|
||||
main() function on program invocation. User options may be specified in the
|
||||
\fIoption_array\fR argument. A help function may be specified in the
|
||||
\fIuser_help_func\fP argument.
|
||||
.sp
|
||||
\fIoption_array\fP is a pointer to the first element of an array of
|
||||
\fBoption_t\fP. If no additional options are needed, pass NULL.
|
||||
\fBoption_t\fR is declared in \fBusctest.h\fP as
|
||||
.nf
|
||||
.sp
|
||||
.in 10
|
||||
typedef struct {
|
||||
.in 14
|
||||
char *option;
|
||||
int *flag;
|
||||
char **arg;
|
||||
.in 10
|
||||
} option_t;
|
||||
.fi
|
||||
.PP
|
||||
The meanings of the different fields are:
|
||||
.TP
|
||||
.I option
|
||||
is a valid option string to be given to getopt().
|
||||
.TP
|
||||
.I flag
|
||||
is a pointer to an integer location to set true if option is given in
|
||||
\fIargv\fR. This can be NULL if the option doesn't require an argument.
|
||||
.TP
|
||||
.I arg
|
||||
is a pointer to a character pointer variable that will be set with the option
|
||||
argument if the option is present in argv. This pointer MUST be provided if
|
||||
the option can take an argument. Failure to provide a location will cause
|
||||
\fBparse_opts()\fR to return an error.
|
||||
.PP
|
||||
.I user_help_func
|
||||
is a pointer to a function that will be called when the \-h option is found.
|
||||
This function should print help messages for the options in \fIoption_array\fR
|
||||
to standard out. The standard help messages are formatted such that the option
|
||||
designator starts in column 3 and the description starts in column 11.
|
||||
.sp
|
||||
.SH "STANDARD OPTIONS"
|
||||
Below is a list of the standard options defined in \fBparse_opts()\fR:
|
||||
.TP
|
||||
.BI \-c " n"
|
||||
Run \fIn\fR copies of the test in parallel. This is done by forking \fIn\fR
|
||||
times and running the test as usual. If \-i or \-I are specified, each process
|
||||
will run for that amount of time.
|
||||
.TP
|
||||
.B \-e
|
||||
Turn on logging all errno's received. This option is to facilitate security
|
||||
audit testing for MLS.
|
||||
.TP
|
||||
.B \-f
|
||||
Suppresses functional testing messages.
|
||||
.TP
|
||||
.B \-h
|
||||
Print help message. The standard options will be printed first, then a call to
|
||||
.I user_help_func()
|
||||
will be made.
|
||||
.TP
|
||||
.BI \-i " n"
|
||||
Run for \fIn\fR iterations. A value of 0 makes the test loop infinitely.
|
||||
(default 1)
|
||||
.TP
|
||||
.BI \-I " x"
|
||||
The test will loop until \fIx\fR seconds have passed. (default 0.0)
|
||||
.TP
|
||||
.B \-p
|
||||
Pause for SIGUSR1 before testing. The test will pause where you place
|
||||
TEST_PAUSE. \fIWarning\fR: The test will also fork at this point if \-c is
|
||||
used.
|
||||
.TP
|
||||
.BI \-P " x"
|
||||
This option will do a delay of \fIx\fR seconds after each iteration. (default 0.0)
|
||||
.TP
|
||||
.B \-t
|
||||
Produce timing statistics. *NOT IMPLEMENTED*
|
||||
.PP
|
||||
.sp
|
||||
The STD_* flags are used by system call test macros defined in usctest.h
|
||||
(see \fBusctest(3)\fR), or may be used in the user's code.
|
||||
.SH "RETURN VALUE"
|
||||
.B parse_opts()
|
||||
returns a NULL pointer upon successful completion. If an error occurs a
|
||||
pointer to an error message is returned.
|
||||
.SH "EXAMPLE"
|
||||
The following example defines two options, one with an argument, one without.
|
||||
.sp
|
||||
.nf
|
||||
int fflag, Tflag; /* binary flags: opt or not */
|
||||
char *Topt; /* option arguments */
|
||||
|
||||
option_t options[] = {
|
||||
{ "F", &fflag, NULL }, /* No argument */
|
||||
{ "T:", &Tflag, &Topt }, /* argument required */
|
||||
{ NULL, NULL, NULL } /* NULL required to end array */
|
||||
};
|
||||
|
||||
void help()
|
||||
{
|
||||
printf(" -F An option with no argument\\n");
|
||||
printf(" -T opt An option that requires an argument\\n");
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
char *msg;
|
||||
|
||||
if ((msg = parse_opts(argc, argv, options, &help)) != NULL)
|
||||
error_exit(msg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
.fi
|
||||
.sp
|
||||
The following example shows how to use \fBparse_opts()\fR without defining new options.
|
||||
.sp
|
||||
.nf
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
char *msg;
|
||||
|
||||
if ((msg = parse_opts(argc, argv, NULL, NULL)) != NULL)
|
||||
error_exit(msg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
.fi
|
||||
.SH "SEE ALSO"
|
||||
usctest(3), getopt(3).
|
||||
@@ -1,169 +0,0 @@
|
||||
.\"
|
||||
.\" $Id: parse_ranges.3,v 1.1 2000/07/27 16:59:03 alaffin Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved.
|
||||
.\"
|
||||
.\" This program is free software; you can redistribute it and/or modify it
|
||||
.\" under the terms of version 2 of the GNU General Public License as
|
||||
.\" published by the Free Software Foundation.
|
||||
.\"
|
||||
.\" This program is distributed in the hope that it would be useful, but
|
||||
.\" WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
.\"
|
||||
.\" Further, this software is distributed without any warranty that it is
|
||||
.\" free of the rightful claim of any third person regarding infringement
|
||||
.\" or the like. Any license provided herein, whether implied or
|
||||
.\" otherwise, applies only to this software file. Patent licenses, if
|
||||
.\" any, provided herein do not apply to combinations of this program with
|
||||
.\" other software, or any other product whatsoever.
|
||||
.\"
|
||||
.\" You should have received a copy of the GNU General Public License along
|
||||
.\" with this program; if not, write the Free Software Foundation, Inc.,
|
||||
.\" 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
.\"
|
||||
.\" Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
|
||||
.\" Mountain View, CA 94043, or:
|
||||
.\"
|
||||
.\" http://www.sgi.com
|
||||
.\"
|
||||
.\" For further information regarding this notice, see:
|
||||
.\"
|
||||
.\" http://oss.sgi.com/projects/GenInfo/NoticeExplan/
|
||||
.\"
|
||||
.TH PARSE_RANGES 3 07/25/2000 "Linux Test Project"
|
||||
.SH NAME
|
||||
parse_ranges \- function to parse a string formatted like 'min:max:mult,...'
|
||||
.SH SYNOPSIS
|
||||
.nf
|
||||
int parse_ranges(char *str, int defmin, int defmax, int defmult, int (*parse_func)(), char **rangeptr, char **errptr);
|
||||
int range_min(char *rbuf, int r);
|
||||
int range_max(char *rbuf, int r);
|
||||
int range_mult(char *rbuf, int r);
|
||||
.fi
|
||||
.SH DESCRIPTION
|
||||
parse_ranges() is a function to parse a comma-separated list of range
|
||||
tokens each having the following form:
|
||||
.SP
|
||||
.nf
|
||||
num
|
||||
or
|
||||
min:max[:mult]
|
||||
.fi
|
||||
|
||||
any of the values may be blank (ie. min::mult, :max, etc.) and default
|
||||
values for missing arguments may be supplied by the caller.
|
||||
|
||||
The special first form is short hand for 'num:num'.
|
||||
|
||||
After parsing the string, the ranges are put into an array of integers,
|
||||
which is malloc'd by the routine. The min, max, and mult entries of each
|
||||
range can be extracted from the array using the range_min(), range_max(),
|
||||
and range_mult() functions.
|
||||
|
||||
If \fIrange_ptr\fP is not NULL, and parse_ranges() successfully parses the
|
||||
range string (ie. does not return -1), *range_ptr will point to space
|
||||
malloc'd by parse_ranges(). The user may free this space by calling free().
|
||||
|
||||
parse_ranges() parameters are:
|
||||
.SP
|
||||
.TP 1i
|
||||
\fIstr\fP
|
||||
The string to parse - assumed to be a comma-separated
|
||||
list of tokens having the above format.
|
||||
.TP 1i
|
||||
\fIdefmin\fP
|
||||
default value to plug in for min, if it is missing
|
||||
.TP 1i
|
||||
\fIdefmax\fP
|
||||
default value to plug in for max, if it is missing
|
||||
.TP 1i
|
||||
\fIdefmult\fP
|
||||
default value to plug in for mult, if missing
|
||||
.TP 1i
|
||||
\fIparse_func\fP
|
||||
A user-supplied function pointer, which parse_ranges()
|
||||
can call to parse the min, max, and mult strings. This
|
||||
allows for customized number formats. The function
|
||||
MUST have the following prototype:
|
||||
.SP
|
||||
.nf
|
||||
int parse_func(char *str, int *val)
|
||||
.fi
|
||||
.SP
|
||||
The function should return -1 if str cannot be parsed
|
||||
into an integer, or >= 0 if it was successfully
|
||||
parsed. The resulting integer will be stored in
|
||||
*val. If parse_func is NULL, parse_ranges will parse
|
||||
the tokens in a manner consistent with the sscanf %i format.
|
||||
.TP 1i
|
||||
\fIrange_ptr\fP
|
||||
A user-supplied char **, which will be set to point
|
||||
at malloc'd space which holds the parsed range
|
||||
values. If range_ptr is NULL, parse_ranges() just
|
||||
parses the string. The data returned in range_ptr
|
||||
should not be processed directly - use the functions
|
||||
range_min(), range_max(), and range_mult() to access
|
||||
data for a given range.
|
||||
.TP 1i
|
||||
\fIerrptr\fP
|
||||
user-supplied char ** which can be set to point to a
|
||||
static error string. If errptr is NULL, it is ignored.
|
||||
.in -1i
|
||||
|
||||
.SP
|
||||
range_min(), range_max(), and range_mult() parameters are:
|
||||
.SP
|
||||
.SP
|
||||
.TP 1i
|
||||
\fIrbuf\fP
|
||||
An array of ranges set up by parse_ranges().
|
||||
.TP 1i
|
||||
\fIr\fP
|
||||
The range number to extract information from. Must be an integer >= 0 and
|
||||
< the number of ranges returned by parse_ranges().
|
||||
.in -1i
|
||||
|
||||
.SH EXAMPLES
|
||||
\fC
|
||||
.ta .25i +.25i +.25i +.25i
|
||||
.nf
|
||||
/*
|
||||
* simple example to take a list of ranges on the cmdline (in argv[1]), and
|
||||
* print a random number from within that range.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
main()
|
||||
{
|
||||
extern int parse_ranges(), range_min(), range_max(), range_mult();
|
||||
extern long random_range(), random_range_seed();
|
||||
int min, max, mult, nranges;
|
||||
char *ep, *rp;
|
||||
|
||||
random_range_seed(getpid());
|
||||
if ((nranges = parse_ranges(argv[1], 0, INT_MAX, 1, NULL, &rp, &ep)) < 0) {
|
||||
fprintf(stderr, "parse_ranges() failed: %s\n", ep);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
range = random_range(0, nranges-1, 1);
|
||||
min = range_min(rp, range);
|
||||
max = range_max(rp, range);
|
||||
mult = range_mult(rp, range);
|
||||
|
||||
fprintf("%d\\n", random_range(min, max-1, mult));
|
||||
exit(0);
|
||||
}
|
||||
\fP
|
||||
.DT
|
||||
.SH "SEE ALSO"
|
||||
random_range(3),
|
||||
random_range_seed(3),
|
||||
bytes_by_prefix(3).
|
||||
.SH DIAGNOSTICS
|
||||
parse_ranges() returns -1 on error or the number of ranges parsed. No space
|
||||
will be malloc'd if parse_ranges() fails. Error
|
||||
messages are passed back through the errptr parameter. There are no error
|
||||
conditions for range_min(), range_max(), or range_mult().
|
||||
@@ -1,114 +0,0 @@
|
||||
.\"
|
||||
.\" $Id: random_range.3,v 1.1 2000/07/27 16:59:03 alaffin Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved.
|
||||
.\"
|
||||
.\" This program is free software; you can redistribute it and/or modify it
|
||||
.\" under the terms of version 2 of the GNU General Public License as
|
||||
.\" published by the Free Software Foundation.
|
||||
.\"
|
||||
.\" This program is distributed in the hope that it would be useful, but
|
||||
.\" WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
.\"
|
||||
.\" Further, this software is distributed without any warranty that it is
|
||||
.\" free of the rightful claim of any third person regarding infringement
|
||||
.\" or the like. Any license provided herein, whether implied or
|
||||
.\" otherwise, applies only to this software file. Patent licenses, if
|
||||
.\" any, provided herein do not apply to combinations of this program with
|
||||
.\" other software, or any other product whatsoever.
|
||||
.\"
|
||||
.\" You should have received a copy of the GNU General Public License along
|
||||
.\" with this program; if not, write the Free Software Foundation, Inc.,
|
||||
.\" 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
.\"
|
||||
.\" Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
|
||||
.\" Mountain View, CA 94043, or:
|
||||
.\"
|
||||
.\" http://www.sgi.com
|
||||
.\"
|
||||
.\" For further information regarding this notice, see:
|
||||
.\"
|
||||
.\" http://oss.sgi.com/projects/GenInfo/NoticeExplan/
|
||||
.\"
|
||||
.TH random_range 3 07/25/2000 "Linux Test Project"
|
||||
.SH NAME
|
||||
random_range \- a set of routines for dealing with integer ranges, and random numbers in a range
|
||||
.SH SYNOPSIS
|
||||
.nf
|
||||
void random_range_seed(int seed)
|
||||
long random_range(int min, int max, int mult, char **errp)
|
||||
long random_rangel(long min, long max, long mult, char **errp)
|
||||
long long random_rangell(long long min, long long max,
|
||||
long long mult, char **errp)
|
||||
long random_bit(long mask)
|
||||
.fi
|
||||
.SH DESCRIPTION
|
||||
This is a set of routines for parsing numeric ranges, and choosing random
|
||||
numbers from a range.
|
||||
|
||||
random_range() chooses a random number in the range min-max (inclusive) which
|
||||
is a multiple of mult. min and max may be any integer, but mult must be
|
||||
a positive integer greater than 0. errp is a char ** which is used to detect
|
||||
error conditions. If errp is not NULL, *errp will be set to point to an
|
||||
error message. If errp is NULL, error conditions cannot be detected by the
|
||||
caller. If mult is 1 (the most common case), there are no possible error
|
||||
conditions, and the return value is guaranteed to be valid.
|
||||
|
||||
random_range_seed() sets the random number generator seed to the specified
|
||||
value.
|
||||
|
||||
random_bit() will return a randomly selected single bit bitmask from the bits
|
||||
set in mask. The bit is randomly chosen using random_range().
|
||||
If mask is zero, zero is returned.
|
||||
|
||||
random_range() functions uses lrand48() internally. If the range is bigger
|
||||
than will fit in a 32 bit long (2G), lrand48() with a
|
||||
a internal recursive algorithm to produce a random number.
|
||||
|
||||
.SH EXAMPLES
|
||||
\fC
|
||||
.ta .25i +.25i +.25i +.25i
|
||||
.nf
|
||||
#include <stdio.h>
|
||||
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
{
|
||||
int r;
|
||||
char *errp;
|
||||
extern void random_range_seed();
|
||||
extern long random_range();
|
||||
|
||||
random_range_seed(getpid());
|
||||
|
||||
r = random_range(atoi(argv[1]), atoi(argv[2]), atoi(argv[3]), &errp);
|
||||
if (errp == NULL) {
|
||||
fprintf(stderr, "random_range failed: %s\n", errp);
|
||||
exit(1);
|
||||
} else {
|
||||
printf("%d\n", r);
|
||||
}
|
||||
|
||||
exit(0);
|
||||
}
|
||||
\fP
|
||||
.fi
|
||||
|
||||
.SH "SEE ALSO"
|
||||
lrand48(3c)
|
||||
.SH DIAGNOSTICS
|
||||
If random_range() fails, errp will point to NULL, and the return value will be
|
||||
undefined. If mult is 1, there are no possible error conditions, so the return
|
||||
value is always valid in this case.
|
||||
|
||||
.SH BUGS
|
||||
On CRAY systems, random_range(), random_rangel(), random_rangell()
|
||||
all have the 64 bit limit since int, long and long long are always 64 bits.
|
||||
|
||||
On IRIX systems, random_range() can only produce a 32 number.
|
||||
random_rangel() when compiled as a 32 bit object is still limited to 32 bit
|
||||
number. random_rangell() can be used to return a value bigger than 32 bits
|
||||
even when compiled as a 32 bit object.
|
||||
|
||||
@@ -1,114 +0,0 @@
|
||||
.\"
|
||||
.\" $Id: random_range_seed.3,v 1.1 2000/07/27 16:59:03 alaffin Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved.
|
||||
.\"
|
||||
.\" This program is free software; you can redistribute it and/or modify it
|
||||
.\" under the terms of version 2 of the GNU General Public License as
|
||||
.\" published by the Free Software Foundation.
|
||||
.\"
|
||||
.\" This program is distributed in the hope that it would be useful, but
|
||||
.\" WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
.\"
|
||||
.\" Further, this software is distributed without any warranty that it is
|
||||
.\" free of the rightful claim of any third person regarding infringement
|
||||
.\" or the like. Any license provided herein, whether implied or
|
||||
.\" otherwise, applies only to this software file. Patent licenses, if
|
||||
.\" any, provided herein do not apply to combinations of this program with
|
||||
.\" other software, or any other product whatsoever.
|
||||
.\"
|
||||
.\" You should have received a copy of the GNU General Public License along
|
||||
.\" with this program; if not, write the Free Software Foundation, Inc.,
|
||||
.\" 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
.\"
|
||||
.\" Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
|
||||
.\" Mountain View, CA 94043, or:
|
||||
.\"
|
||||
.\" http://www.sgi.com
|
||||
.\"
|
||||
.\" For further information regarding this notice, see:
|
||||
.\"
|
||||
.\" http://oss.sgi.com/projects/GenInfo/NoticeExplan/
|
||||
.\"
|
||||
.TH random_range 3 07/25/2000 "Linux Test Project"
|
||||
.SH NAME
|
||||
random_range \- a set of routines for dealing with integer ranges, and random numbers in a range
|
||||
.SH SYNOPSIS
|
||||
.nf
|
||||
void random_range_seed(int seed)
|
||||
long random_range(int min, int max, int mult, char **errp)
|
||||
long random_rangel(long min, long max, long mult, char **errp)
|
||||
long long random_rangell(long long min, long long max,
|
||||
long long mult, char **errp)
|
||||
long random_bit(long mask)
|
||||
.fi
|
||||
.SH DESCRIPTION
|
||||
This is a set of routines for parsing numeric ranges, and choosing random
|
||||
numbers from a range.
|
||||
|
||||
random_range() chooses a random number in the range min-max (inclusive) which
|
||||
is a multiple of mult. min and max may be any integer, but mult must be
|
||||
a positive integer greater than 0. errp is a char ** which is used to detect
|
||||
error conditions. If errp is not NULL, *errp will be set to point to an
|
||||
error message. If errp is NULL, error conditions cannot be detected by the
|
||||
caller. If mult is 1 (the most common case), there are no possible error
|
||||
conditions, and the return value is guaranteed to be valid.
|
||||
|
||||
random_range_seed() sets the random number generator seed to the specified
|
||||
value.
|
||||
|
||||
random_bit() will return a randomly selected single bit bitmask from the bits
|
||||
set in mask. The bit is randomly chosen using random_range().
|
||||
If mask is zero, zero is returned.
|
||||
|
||||
random_range() functions uses lrand48() internally. If the range is bigger
|
||||
than will fit in a 32 bit long (2G), lrand48() with a
|
||||
a internal recursive algorithm to produce a random number.
|
||||
|
||||
.SH EXAMPLES
|
||||
\fC
|
||||
.ta .25i +.25i +.25i +.25i
|
||||
.nf
|
||||
#include <stdio.h>
|
||||
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
{
|
||||
int r;
|
||||
char *errp;
|
||||
extern void random_range_seed();
|
||||
extern long random_range();
|
||||
|
||||
random_range_seed(getpid());
|
||||
|
||||
r = random_range(atoi(argv[1]), atoi(argv[2]), atoi(argv[3]), &errp);
|
||||
if (errp == NULL) {
|
||||
fprintf(stderr, "random_range failed: %s\n", errp);
|
||||
exit(1);
|
||||
} else {
|
||||
printf("%d\n", r);
|
||||
}
|
||||
|
||||
exit(0);
|
||||
}
|
||||
\fP
|
||||
.fi
|
||||
|
||||
.SH "SEE ALSO"
|
||||
lrand48(3c)
|
||||
.SH DIAGNOSTICS
|
||||
If random_range() fails, errp will point to NULL, and the return value will be
|
||||
undefined. If mult is 1, there are no possible error conditions, so the return
|
||||
value is always valid in this case.
|
||||
|
||||
.SH BUGS
|
||||
On CRAY systems, random_range(), random_rangel(), random_rangell()
|
||||
all have the 64 bit limit since int, long and long long are always 64 bits.
|
||||
|
||||
On IRIX systems, random_range() can only produce a 32 number.
|
||||
random_rangel() when compiled as a 32 bit object is still limited to 32 bit
|
||||
number. random_rangell() can be used to return a value bigger than 32 bits
|
||||
even when compiled as a 32 bit object.
|
||||
|
||||
@@ -1,313 +0,0 @@
|
||||
.\"
|
||||
.\" $Id: tst_res.3,v 1.2 2008/06/10 05:52:02 subrata_modak Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved.
|
||||
.\"
|
||||
.\" This program is free software; you can redistribute it and/or modify it
|
||||
.\" under the terms of version 2 of the GNU General Public License as
|
||||
.\" published by the Free Software Foundation.
|
||||
.\"
|
||||
.\" This program is distributed in the hope that it would be useful, but
|
||||
.\" WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
.\"
|
||||
.\" Further, this software is distributed without any warranty that it is
|
||||
.\" free of the rightful claim of any third person regarding infringement
|
||||
.\" or the like. Any license provided herein, whether implied or
|
||||
.\" otherwise, applies only to this software file. Patent licenses, if
|
||||
.\" any, provided herein do not apply to combinations of this program with
|
||||
.\" other software, or any other product whatsoever.
|
||||
.\"
|
||||
.\" You should have received a copy of the GNU General Public License along
|
||||
.\" with this program; if not, write the Free Software Foundation, Inc.,
|
||||
.\" 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
.\"
|
||||
.\" Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
|
||||
.\" Mountain View, CA 94043, or:
|
||||
.\"
|
||||
.\" http://www.sgi.com
|
||||
.\"
|
||||
.\" For further information regarding this notice, see:
|
||||
.\"
|
||||
.\" http://oss.sgi.com/projects/GenInfo/NoticeExplan/
|
||||
.\"
|
||||
.TH TST_RES 3 01/21/2011 "Linux Test Project"
|
||||
.SH NAME
|
||||
tst_resm \- Print result message
|
||||
.sp
|
||||
tst_resm_hexd \- Print result message, including specified buffer in hexadecimal format
|
||||
.sp
|
||||
tst_brkm \- Print result message and break remaining test cases
|
||||
.sp
|
||||
tst_old_flush \- Print any messages pending because of CONDENSE mode, and flush output stream
|
||||
.sp
|
||||
tst_exit \- Exit test with a meaningful exit value
|
||||
.sp
|
||||
tst_environ \- Keep results coming to original stdout
|
||||
.SH SYNOPSIS
|
||||
\fB#include "test.h"\fR
|
||||
.P
|
||||
.P
|
||||
\fBvoid tst_resm(int \fIttype\fB, char *\fItmesg, [arg ...]\fR)
|
||||
.P
|
||||
\fBvoid tst_resm_hexd(int \fIttype\fB, const void *\fIbuf\fB, size_t \fIsize\fB,
|
||||
char *\fItmesg, [arg ...]\fR)
|
||||
.P
|
||||
\fBvoid tst_brkm(int \fIttype\fB, void (*\fIfunc\fB)(), char *\fItmesg,
|
||||
[arg ...]\fR)
|
||||
.P
|
||||
\fBvoid tst_old_flush()
|
||||
.P
|
||||
\fBvoid tst_exit()
|
||||
.P
|
||||
\fBint tst_environ()
|
||||
.P
|
||||
\fBextern int tst_count;
|
||||
.br
|
||||
extern int tst_range;
|
||||
.br
|
||||
\fR
|
||||
.SH DESCRIPTION
|
||||
.SS Introduction
|
||||
This library of functions are used by UNICOS tests to report results to
|
||||
standard output in a consistent manner. It is assumed that tests using this
|
||||
library have a distinct number of test cases, and that each test case is
|
||||
distinct and uniquely identified by the test case number. It is also assumed
|
||||
that test case results are printed in consecutive order, starting with 1.
|
||||
The library maintains a set of global variables (\fBTCID\fR, \fBTST_TOTAL\fR,
|
||||
\fBtst_count\fR), which are used by the various functions to format the
|
||||
results and to keep track of the current result reporting state (i.e. how many
|
||||
total test cases there are, and how many have been reported so far) for the
|
||||
calling test.
|
||||
.P
|
||||
The \fBTCID\fR and \fBTST_TOTAL\fR global variables are externed in the
|
||||
library, and MUST be defined/initialized by tests using the library.
|
||||
\fBTCID\fR must be set to the \fBT\fRest \fBC\fRase \fBID\fRentifier, and
|
||||
\fBTST_TOTAL\fR must be set to the total number of test cases that will be
|
||||
reported.
|
||||
.P
|
||||
The other global variables are available as externs to tests linked with
|
||||
tst_res.o. \fBtst_count\fR is the running count of the number of test
|
||||
results that have been reported so far. The library initializes it to 0, and
|
||||
it should not be modified by the test.
|
||||
The details are described below under the appropriate functions.
|
||||
.SS Arguments
|
||||
.RS 5
|
||||
.TP 10
|
||||
.I ttype
|
||||
test result type; one of \fBTPASS, TFAIL, TBROK, TCONF, TWARN\fR, or
|
||||
\fBTINFO\fR (explained below).
|
||||
.TP 10
|
||||
.I fname
|
||||
pointer to a character string holding the name of a file whose contents will
|
||||
be printed on a new line following \fItmesg\fR. If this pointer is NULL, it
|
||||
is ignored.
|
||||
.TP 10
|
||||
.I tmesg, [arg ...]
|
||||
pointer to a character string containing a message explaining the test
|
||||
result. This character string can contain percent-sign conversion
|
||||
specifications as in \fBprintf\fR(3C) with corresponding \fIarg\fR arguments
|
||||
following the \fItmesg\fR argument.
|
||||
.br
|
||||
\fBNOTE:\fR These routines use static space internally to hold the
|
||||
expanded message. The maximum size allowed for an expanded message is
|
||||
2048 bytes.
|
||||
.TP 10
|
||||
.I func
|
||||
pointer to a function which performs either the cleanup necessary prior to
|
||||
exiting the test or some function executed at the end of each iteration of a
|
||||
loop.
|
||||
.TP 10
|
||||
.I buf
|
||||
pointer to a buffer whose contents will be printed in hexadecimal format.
|
||||
.TP 10
|
||||
.I size
|
||||
size of the buffer.
|
||||
.RE
|
||||
.SS Result Types
|
||||
The possible test result types defined in \fBtest.h\fR are as follows:
|
||||
.RS 5
|
||||
.TP 10
|
||||
.B TPASS
|
||||
The test case produced expected results.
|
||||
.TP 10
|
||||
.B TFAIL
|
||||
The test case produced unexpected results.
|
||||
.TP 10
|
||||
.B TBROK
|
||||
A resource needed to execute the test case was not available (e.g. a
|
||||
temporary file could not be opened).
|
||||
.TP 10
|
||||
.B TCONF
|
||||
The test case was not appropriate for the current hardware or software
|
||||
configuration (e.g. MLS was not enabled).
|
||||
.TP 10
|
||||
.B TWARN
|
||||
The testing procedure caused undesirable side effects that did not affect
|
||||
test results (e.g. a temporary file could not be removed after all test
|
||||
results were recorded).
|
||||
.TP 10
|
||||
.B TINFO
|
||||
An informative message about the execution of the test that does not
|
||||
correspond to a test case result and does not indicate a problem.
|
||||
.RE
|
||||
.SS Function Descriptions
|
||||
|
||||
\fBtst_resm()\fR and \fBtst_resm_hexd()\fR are the basic
|
||||
result reporting functions. They report 1 or more test case results of the
|
||||
specified \fIttype\fR. All result types are valid for these functions. The
|
||||
\fBtst_range\fR global variable indicates the number of results that will be
|
||||
reported for each call to one of these functions. It is initialized by the
|
||||
library to 1, but may be set to a value > 1 by the test. Each call to one of
|
||||
these functions will result in \fBtst_range\fR test case results being
|
||||
reported, each with an identical message (\fItmesg\fR). \fBtst_range\fR is
|
||||
always reset to 1 by the library before returning to the caller.
|
||||
.P
|
||||
\fBtst_brk()\fR and \fBtst_brkm()\fR are used to report results for all test
|
||||
cases remaining in the test, and then call a cleanup function. The only
|
||||
result types that are valid for these functions are: \fBTFAIL, TBROK,
|
||||
and TCONF\fR. When called with a \fIttype\fR of \fBTFAIL\fR or
|
||||
\fBTBROK\fR, one result of the specified \fIttype\fR will be printed,
|
||||
followed by results of type \fBTBROK\fR for the remaining test cases. When
|
||||
called with a \fIttype\fR of \fBTCONF\fR, the specified
|
||||
\fIttype\fR will be printed for all remaining test cases. If \fIfunc\fR is
|
||||
not NULL, \fBtst_brk()\fR and \fBtst_brkm()\fR will call \fIfunc\fR after all
|
||||
results have been printed. If the call to \fIfunc\fR returns,
|
||||
\fBtst_brk()\fR and \fBtst_brkm()\fR will then call \fBtst_exit()\fR. If
|
||||
\fIfunc\fR is NULL, \fBtst_brk()\fR and \fBtst_brkm()\fR return to the caller
|
||||
after all results have been printed. If \fBtst_brk()\fR is called with a
|
||||
\fIfname\fR argument, the contents of the file will only be printed for the
|
||||
first reported result. \fBtst_brk()\fR takes the \fIfname\fR argument
|
||||
whereas \fBtst_brkm()\fR does not.
|
||||
.P
|
||||
\fBtst_old_flush()\fR is used to print any results pending because of
|
||||
\fBCONDENSE\fR or \fBNOPASS\fR modes (described below), and flushes the
|
||||
output stream.
|
||||
.P
|
||||
\fBtst_exit()\fR is used to allow tests to exit with a meaningful exit
|
||||
value. A bit is set in the exit value for each of the non passing test
|
||||
case result types (TFAIL, TBROK, and TWARN) encountered by the library.
|
||||
Thus any bit which is set in the exit value indicates that the
|
||||
corresponding result flag was used at least once in the test run.
|
||||
.P
|
||||
The current bit fields for the result types are as follows:
|
||||
.RS 5
|
||||
.TP 10
|
||||
TPASS
|
||||
0000 /* .... .... */
|
||||
.TP 10
|
||||
TFAIL
|
||||
0001 /* .... ...1 */
|
||||
.TP 10
|
||||
TBROK
|
||||
0002 /* .... ..1. */
|
||||
.TP 10
|
||||
TWARN
|
||||
0004 /* .... .1.. */
|
||||
.TP 10
|
||||
TINFO
|
||||
0020 /* ...1 .... */
|
||||
.TP 10
|
||||
TCONF
|
||||
0040 /* ..1. .... */
|
||||
.RE
|
||||
.P
|
||||
NOTE: \fBTPASS and TINFO\fR do not have an effect
|
||||
on the test program exit status.
|
||||
.P
|
||||
\fBtst_environ()\fR is used to ensure that results reported by this library
|
||||
will go to the original stdout, even if the test changes the original stdout
|
||||
to another file, or closes it. A test may want to do this in order to
|
||||
redirect output that normally goes to stdout (e.g. printf() output) to a
|
||||
file. \fBtst_environ()\fR returns 0 upon successful completion, and -1 if it
|
||||
encountered any problems.
|
||||
.SS Output Modes
|
||||
Four output display modes are supported by the \fBtst_resm()\fR family of
|
||||
functions to enhance output readability. The active mode is controlled via
|
||||
the environment variable \fBTOUTPUT\fR, which must be set prior to the start
|
||||
of the test in order to have any effect (see \fBksh\fR(1) for information on
|
||||
environment variables). The supported modes are as follows:
|
||||
.RS 5
|
||||
.TP 15
|
||||
.B VERBOSE
|
||||
A test result output line is generated for each test result. This is the
|
||||
default mode.
|
||||
.TP 15
|
||||
.B CONDENSE
|
||||
Consecutive, identical PASS, FAIL, BROK, CONF, and RETR test results are
|
||||
condensed into one output line. The test case number field contains the range
|
||||
of results involved. WARN and INFO output lines are not condensed, but
|
||||
printed as usual.
|
||||
.TP 15
|
||||
.B NOPASS
|
||||
All PASS, CONF, INFO, and RETR output lines are discarded (i.e. not printed),
|
||||
and consecutive, identical FAIL and BROK output lines are condensed as in
|
||||
\fBCONDENSE\fR mode. WARN output lines are printed as usual.
|
||||
.TP 15
|
||||
.B DISCARD
|
||||
All output lines are discarded.
|
||||
.RE
|
||||
.SH EXAMPLES
|
||||
.nf
|
||||
#include "test.h"
|
||||
|
||||
char *TCID = "tsttcs01"; /* set test case identifier */
|
||||
int TST_TOTAL = 15; /* set total number of test results */
|
||||
|
||||
main()
|
||||
{
|
||||
.
|
||||
.
|
||||
/* a successful test result */
|
||||
tst_resm(TPASS, "\fIwhat was tested\fR");
|
||||
.
|
||||
.
|
||||
|
||||
/* break all remaining test results */
|
||||
tst_brkm(TBROK, cleanup, "\fIwhat didn't work\fR");
|
||||
/* or */
|
||||
tst_brk(TBROK, file, cleanup, "\fIwhat didn't work\fR");
|
||||
.
|
||||
.
|
||||
|
||||
/* exit after all test results have been passed to tst_res */
|
||||
tst_exit();
|
||||
}
|
||||
.fi
|
||||
.P
|
||||
Sample output:
|
||||
.RS 5
|
||||
.nf
|
||||
tsttcs01 1 PASS : Able to create MAXUP processes
|
||||
tsttcs01 2 FAIL : Too many processes (MAXUP+1) created
|
||||
tsttcs01 3 BROK : tabinfo(PROCTAB, &tbs) failed; errno = 13: Permission denied
|
||||
.fi
|
||||
.SH "SEE ALSO"
|
||||
tst_setup(1),
|
||||
printf(3C),
|
||||
ksh(1).
|
||||
.SH DIAGNOSTICS
|
||||
.P
|
||||
A WARN result message will be printed if any of the following occur:
|
||||
.RS 5
|
||||
.P
|
||||
If an invalid test type is specified.
|
||||
.P
|
||||
If \fBtst_count\fR is negative.
|
||||
.P
|
||||
If one of the \fBtst_brk[m]()\fR routines is called with a test type
|
||||
other than \fBTFAIL, TBROK, TCONF\fR.
|
||||
.P
|
||||
If there are any problems opening/reading/writing the contents of \fIfname\fR.
|
||||
.RE
|
||||
.SH LIMITATIONS
|
||||
If \fIfname\fR is NULL and \fItmesg\fR is NULL or empty, the result message
|
||||
will be empty. This allows a test to not print a message for a result, but
|
||||
it is not advised.
|
||||
.SH NOTES
|
||||
In multithreaded environment, output of \fBtst_resm_hexd()\fR may be interleaved
|
||||
with messages produced by other threads.
|
||||
.SH BUGS
|
||||
.P
|
||||
The programmer is free to alter the value of \fBtst_count\fR causing possible
|
||||
test result order problems.
|
||||
@@ -1,141 +0,0 @@
|
||||
.\"
|
||||
.\" $Id: tst_sig.3,v 1.1 2000/07/27 16:59:03 alaffin Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved.
|
||||
.\"
|
||||
.\" This program is free software; you can redistribute it and/or modify it
|
||||
.\" under the terms of version 2 of the GNU General Public License as
|
||||
.\" published by the Free Software Foundation.
|
||||
.\"
|
||||
.\" This program is distributed in the hope that it would be useful, but
|
||||
.\" WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
.\"
|
||||
.\" Further, this software is distributed without any warranty that it is
|
||||
.\" free of the rightful claim of any third person regarding infringement
|
||||
.\" or the like. Any license provided herein, whether implied or
|
||||
.\" otherwise, applies only to this software file. Patent licenses, if
|
||||
.\" any, provided herein do not apply to combinations of this program with
|
||||
.\" other software, or any other product whatsoever.
|
||||
.\"
|
||||
.\" You should have received a copy of the GNU General Public License along
|
||||
.\" with this program; if not, write the Free Software Foundation, Inc.,
|
||||
.\" 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
.\"
|
||||
.\" Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
|
||||
.\" Mountain View, CA 94043, or:
|
||||
.\"
|
||||
.\" http://www.sgi.com
|
||||
.\"
|
||||
.\" For further information regarding this notice, see:
|
||||
.\"
|
||||
.\" http://oss.sgi.com/projects/GenInfo/NoticeExplan/
|
||||
.\"
|
||||
.TH TST_SIG 3 07/25/2000 "Linux Test Project"
|
||||
.SH NAME
|
||||
tst_sig \- set up for unexpected signals
|
||||
.SH SYNOPSIS
|
||||
.nf
|
||||
\fB
|
||||
#include "test.h"
|
||||
|
||||
void tst_sig(fork_flag, handler, cleanup)
|
||||
char *fork_flag;
|
||||
int (*handler)();
|
||||
void (*cleanup)();
|
||||
\fR
|
||||
.fi
|
||||
.SH DESCRIPTION
|
||||
.P
|
||||
\fItst_sig\fR is used by UNICOS test case programs
|
||||
to set up signal handling functions for unexpected
|
||||
signals. This provides test cases with a graceful means
|
||||
of exiting following an unexpected interruption by a signal.
|
||||
\fItst_sig\fR should be called only once by a test
|
||||
program.
|
||||
.P
|
||||
The \fIfork_flag\fR parameter is used to tell \fItst_sig\fR
|
||||
whether or not to ignore the SIGCHLD signal caused by the death of a
|
||||
child process that had previously been created by the
|
||||
\fIfork\fR(2) system call (see \fIsignal\fR(2) for more
|
||||
information on the SIGCHLD signal).
|
||||
.P
|
||||
Setting \fIfork_flag\fR to FORK will cause \fItst_sig\fR to
|
||||
ignore the SIGCHLD signal. This option should be set if the
|
||||
test program directly (eg. call \fIfork\fR(2)) or indirectly
|
||||
(eg. call \fIsystem\fR(3S)) creates a child process.
|
||||
.P
|
||||
Setting \fIfork_flag\fR to NOFORK will cause \fItst_sig\fR to
|
||||
treat the SIGCHLD signal just as any other unexpected
|
||||
signal (ie. the \fIhandler\fR will be called).
|
||||
This option should be set by any test program which does not
|
||||
directly or indirectly create any child processes.
|
||||
.P
|
||||
The \fIhandler\fR parameter is
|
||||
a pointer to a function returning type int which is
|
||||
executed upon the receipt of an unexpected signal.
|
||||
The test program may pass a pointer to a signal handling
|
||||
function or it may elect to use a \fIdefault handler\fR
|
||||
supplied by \fItst_sig\fR.
|
||||
|
||||
The \fIdefault handler\fR is specified by passing DEF_HANDLER
|
||||
as the \fIhandler\fR argument. Upon receipt of an unexpected
|
||||
signal, the \fIdefault handler\fR will generate
|
||||
\fItst_res\fR(3) messages for all test results that had
|
||||
not been completed at the time of the signal, execute the
|
||||
\fIcleanup\fR routine, if provided, and call \fItst_exit\fR.
|
||||
Note: if the \fIdefault handler\fR is used, the variables
|
||||
\fBTCID\fR and \fBtst_count\fR must be defined and available to
|
||||
\fItst_sig\fR (see \fItst_res\fR(3)).
|
||||
.P
|
||||
The \fIcleanup\fR parameter is a pointer to a user-defined
|
||||
function returning type void which is executed
|
||||
by the \fIdefault handler\fR. The \fIcleanup\fR function
|
||||
should remove any files, directories, processes, etc. created
|
||||
by the test program.
|
||||
If no cleanup is required, this parameter should be set to NULL.
|
||||
|
||||
.SH EXAMPLES
|
||||
|
||||
.nf
|
||||
#include "test.h"
|
||||
|
||||
/*
|
||||
* the TCID and TST_TOTAL variables must be available to tst_sig
|
||||
* if the \fIdefault handler\fR is used. The \fIdefault handler\fR will call
|
||||
* \fItst_res\fR(3) and will need this information.
|
||||
*/
|
||||
int TCID = "tsttcs01"; /* set test case identifier */
|
||||
int TST_TOTAL = 5; /* set total number of test results */
|
||||
|
||||
|
||||
void tst_sig();
|
||||
|
||||
/*
|
||||
* set up for unexpected signals:
|
||||
* no \fIfork\fR() system calls will be executed during the test run
|
||||
* use the default signal handler provided by \fItst_sig\fR
|
||||
* no cleanup is necessary
|
||||
*/
|
||||
tst_sig(NOFORK, DEF_HANDLER, NULL);
|
||||
|
||||
|
||||
void tst_sig(), cleanup();
|
||||
int handler();
|
||||
|
||||
/*
|
||||
* set up for unexpected signals:
|
||||
* \fIfork\fR() system calls will be executed during the test run
|
||||
* use user-defined signal handler
|
||||
* use cleanup
|
||||
*/
|
||||
tst_sig(FORK, handler, cleanup);
|
||||
|
||||
.fi
|
||||
.SH "SEE ALSO"
|
||||
signal(2),
|
||||
tst_setup(1).
|
||||
.SH DIAGNOSTICS
|
||||
.P
|
||||
\fItst_sig\fR will output warnings in standard \fItst_res\fR
|
||||
format if it cannot set up the signal handlers.
|
||||
@@ -1,76 +0,0 @@
|
||||
.\"
|
||||
.\" $Id: tst_tmpdir.3,v 1.1 2000/07/27 16:59:03 alaffin Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved.
|
||||
.\"
|
||||
.\" This program is free software; you can redistribute it and/or modify it
|
||||
.\" under the terms of version 2 of the GNU General Public License as
|
||||
.\" published by the Free Software Foundation.
|
||||
.\"
|
||||
.\" This program is distributed in the hope that it would be useful, but
|
||||
.\" WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
.\"
|
||||
.\" Further, this software is distributed without any warranty that it is
|
||||
.\" free of the rightful claim of any third person regarding infringement
|
||||
.\" or the like. Any license provided herein, whether implied or
|
||||
.\" otherwise, applies only to this software file. Patent licenses, if
|
||||
.\" any, provided herein do not apply to combinations of this program with
|
||||
.\" other software, or any other product whatsoever.
|
||||
.\"
|
||||
.\" You should have received a copy of the GNU General Public License along
|
||||
.\" with this program; if not, write the Free Software Foundation, Inc.,
|
||||
.\" 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
.\"
|
||||
.\" Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
|
||||
.\" Mountain View, CA 94043, or:
|
||||
.\"
|
||||
.\" http://www.sgi.com
|
||||
.\"
|
||||
.\" For further information regarding this notice, see:
|
||||
.\"
|
||||
.\" http://oss.sgi.com/projects/GenInfo/NoticeExplan/
|
||||
.\"
|
||||
.TH TST_TMPDIR 3 07/25/2000 "Linux Test Project"
|
||||
.SH NAME
|
||||
tst_tmpdir \- create a unique testing directory and make it current.
|
||||
.br
|
||||
tst_rmdir \- remove the directory created by \fBtst_tmpdir\fR.
|
||||
.SH SYNOPSIS
|
||||
\fBvoid tst_tmpdir()
|
||||
.P
|
||||
void tst_rmdir()
|
||||
.P
|
||||
extern char *TESTDIR;\fR
|
||||
.SH DESCRIPTION
|
||||
The \fBtst_tmpdir()\fR function uses the first three characters of the
|
||||
\fBTCID\fR global variable as the prefix in forming a unique directory name
|
||||
(via \fBtempnam\fR(3S)). The directory is then created and made the current
|
||||
working directory.
|
||||
.P
|
||||
If \fBtst_tmpdir()\fR cannot form a unique directory name, create the
|
||||
directory, or \fBchdir\fR to the directory, it uses \fBtst_brk()\fR to issue
|
||||
"BROK" messages for all test cases. It then exits via \fBtst_exit()\fR.
|
||||
Because \fBtst_tmpdir()\fR exits in the event of a problem, a test must call
|
||||
it \fBbefore\fR performing any operations that would require running a
|
||||
cleanup routine.
|
||||
.P
|
||||
The \fBtst_rmdir()\fR function recursively removes the directory created by
|
||||
\fBtst_tmpdir()\fR. This function should be used \fBonly\fR as a companion
|
||||
to \fBtst_tmpdir()\fR and should be called immediately prior to the test
|
||||
exiting via \fBtst_exit()\fR.
|
||||
.P
|
||||
\fBtst_rmdir()\fR uses the \fBsystem\fR(3S) library routine (which in turn
|
||||
calls \fBfork\fR(2)), so tests that use it \fBcannot\fR treat SIGCHLD as an
|
||||
unexpected signal.
|
||||
.P
|
||||
Users may gain access to the name of the temporary directory by declaring the
|
||||
external character pointer \fBTESTDIR\fR.
|
||||
.SH DIAGNOSTICS
|
||||
The \fBtst_rmdir()\fR function will check the \fBTESTDIR\fR global variable
|
||||
to ensure that the user is not attempting to remove the root directory or
|
||||
some unspecified directories with a "*" parameter. All error/warning
|
||||
messages are delivered through \fBtst_resm()\fR.
|
||||
.SH "SEE ALSO"
|
||||
fork(2), system(3S), tst_res(3), tmpnam(3S).
|
||||
|
||||
@@ -1,164 +0,0 @@
|
||||
.\" $Id: usctest.3,v 1.2 2000/08/31 18:40:28 nstraz Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved.
|
||||
.\"
|
||||
.\" This program is free software; you can redistribute it and/or modify it
|
||||
.\" under the terms of version 2 of the GNU General Public License as
|
||||
.\" published by the Free Software Foundation.
|
||||
.\"
|
||||
.\" This program is distributed in the hope that it would be useful, but
|
||||
.\" WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
.\"
|
||||
.\" Further, this software is distributed without any warranty that it is
|
||||
.\" free of the rightful claim of any third person regarding infringement
|
||||
.\" or the like. Any license provided herein, whether implied or
|
||||
.\" otherwise, applies only to this software file. Patent licenses, if
|
||||
.\" any, provided herein do not apply to combinations of this program with
|
||||
.\" other software, or any other product whatsoever.
|
||||
.\"
|
||||
.\" You should have received a copy of the GNU General Public License along
|
||||
.\" with this program; if not, write the Free Software Foundation, Inc.,
|
||||
.\" 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
.\"
|
||||
.\" Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
|
||||
.\" Mountain View, CA 94043, or:
|
||||
.\"
|
||||
.\" http://www.sgi.com
|
||||
.\"
|
||||
.\" For further information regarding this notice, see:
|
||||
.\"
|
||||
.\" http://oss.sgi.com/projects/GenInfo/NoticeExplan/
|
||||
.\"
|
||||
.TH USCTEST 3 01/21/2011 "Linux Test Project"
|
||||
.SH NAME
|
||||
usctest \- macros and libraries for common functions in system call tests
|
||||
.SH SYNOPSIS
|
||||
\fBRoutines:\fR
|
||||
.br
|
||||
.in +1
|
||||
char *\fBparse_opts(\fI...\fB)\fR
|
||||
.in -1
|
||||
.sp
|
||||
\fBMacros\fR
|
||||
.in +1
|
||||
.br
|
||||
\fBTEST_PAUSE\fR
|
||||
.br
|
||||
\fBTEST(\fIsyscall\fB)\fR
|
||||
.br
|
||||
.\"\fBTEST_CALLER(\fIsyscall\fB, \fIpid\fB)\fR
|
||||
.\".br
|
||||
\fBTEST_VOID(\fIsyscall\fB)\fR
|
||||
.br
|
||||
\fBTEST_CLEANUP\fR
|
||||
.br
|
||||
\fBTEST_LOOPING(\fIcounter\fB)\fR
|
||||
.br
|
||||
\fBTEST_ERROR_LOG(\fIerrno\fB)\fR
|
||||
.br
|
||||
\fBTEST_EXP_ENOS(\fIarray\fB)\fR
|
||||
.in -1
|
||||
.sp
|
||||
\fBGlobal Variable(s)\fR (see \fBparse_opts(3)\fR for complete list):
|
||||
.br
|
||||
.in +1
|
||||
int \fBTEST_RETURN\fR; /* set by the \fBTEST\fR macro to the return code from \fIsyscall\fR */
|
||||
.br
|
||||
int \fBTEST_ERRNO\fR; /* set by the \fBTEST\fR macro to the value of \fBerrno\fR after \fIsyscall\fR returns */
|
||||
.br
|
||||
/* All STD_* variables referenced below are set by the \fBparse_opts(3)\fR routine. */
|
||||
.in -1
|
||||
|
||||
.SH DESCRIPTION
|
||||
The \fBTEST_PAUSE\fR macro checks if the global variable STD_PAUSE is set. If so, it
|
||||
pauses for a SIGUSR1 before continuing execution. The signal handler used does nothing.
|
||||
After the signal is processed, the previous action is replaced for SIGUSR1.
|
||||
.sp
|
||||
The \fBTEST(\fIsyscall\fB)\fR macro executes (\fIsyscall\fR) and times its execution.
|
||||
It saves the max time, min time, accumulated time, and
|
||||
execution count, if STD_TIMING_ON is set.
|
||||
.sp
|
||||
.\"The\fBTEST_CALLER(\fIsyscall\fB, \fIpid\fB)\fR macro executes (\fIsyscall\fR) and times its execution.
|
||||
.\"It saves the max time, min time, accumulated time, and
|
||||
.\"execution count, if STD_TIMING_ON is set and if \fIpid\fR is equal to the current pid.
|
||||
.\".sp
|
||||
The \fBTEST_VOID(\fIsyscall\fB)\fR macro works exactly the same as the \fBTEST()\fR
|
||||
macro except that it does NOT set the global \fBTEST_RETURN\fR. It is intended
|
||||
to be used with system calls that do not have a return value.
|
||||
.sp
|
||||
The \fBTEST_CLEANUP\fR macro prints timing statistics,
|
||||
accumulated through the TEST macro, if STD_TIMING_ON is set. Also, prints the \fBerrno\fR return
|
||||
counts as logged by the \fBTEST_ERROR_LOG\fR macro, if STD_ERR_LOG is set. \fBTEST_CLEANUP\fR uses
|
||||
\fBtst_resm(3)\fR to output this information.
|
||||
.sp
|
||||
The \fBTEST_LOOPING(\fIcounter\fB)\fR macro checks \fIcounter\fR against
|
||||
the global variable STD_LOOP_COUNTER. If \fIcounter\fR is less than STD_LOOP_COUNTER or STD_INFINITE
|
||||
is set, it returns TRUE.
|
||||
.sp
|
||||
The \fBTEST_ERROR_LOG\fR macro records the return of \fIerrno\fR as unexpected, unless the option to
|
||||
turn it off is specified on the command line.
|
||||
.sp
|
||||
The \fBTEST_EXP_ENOS(\fIarray\fB)\fR macro sets an internal flag for each errno in \fIarray\fR, indicating
|
||||
that the errno is expected at some point in the test. This is used by the TEST_CLEANUP macro to determine
|
||||
which errnos are expected when printing the log. The \fIarray\fR must be zero terminated.
|
||||
.sp
|
||||
The \fBparse_opts\fR routine parses the command line (see \fBparse_opts(3)\fR). All STD_* global
|
||||
variables used are set by the \fBparse_opts(3)\fR routine.
|
||||
|
||||
.SH EXAMPLES
|
||||
Below is a partial template of a system call test using these routines, macros, and global variables.
|
||||
|
||||
.nf
|
||||
void setup(void)
|
||||
{
|
||||
TEST_PAUSE; /* Pause if option specified */
|
||||
}
|
||||
|
||||
void cleanup(void)
|
||||
{
|
||||
TEST_CLEANUP;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int lc;
|
||||
char *msg;
|
||||
|
||||
int exp_enos[]={EACCESS, 0};
|
||||
|
||||
|
||||
TEST_EXP_ENOS(exp_enos); /* set expected errnos */
|
||||
|
||||
setup(); /* execute setup */
|
||||
|
||||
/* parse options */
|
||||
msg = parse_opts(ac, av, NULL, NULL);
|
||||
|
||||
/* Check parse_opts return */
|
||||
|
||||
for (lc=0; TEST_LOOPING(lc); lc++) {
|
||||
TEST(open("file", O_RDWR))
|
||||
|
||||
if (TEST_RETURN == -1) {
|
||||
TEST_ERROR_LOG(TEST_ERRNO)
|
||||
/* BREAK test case, or whatever... */
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
cleanup();
|
||||
tst_exit();
|
||||
}
|
||||
.fi
|
||||
|
||||
.SH "SEE ALSO"
|
||||
parse_opts(3).
|
||||
|
||||
.SH "RETURN VALUES"
|
||||
The TEST_LOOPING macro evaluates to TRUE (1) or FALSE (0), and is intended for
|
||||
use in while or for loops. The TEST macro places the return value from
|
||||
\fIsyscall\fR in the global variable TEST_RETURN and the errno in the global
|
||||
variable TEST_ERRNO. The \fBTEST_PAUSE\fR, \fBTEST_CLEANUP\fR,
|
||||
\fBTEST_ERROR_LOG\fR, and \fBTEST_EXP_ENOS\fR macros do not have any return
|
||||
values.
|
||||
@@ -1,171 +0,0 @@
|
||||
-------------
|
||||
--- Intro ---
|
||||
-------------
|
||||
|
||||
Linux running on processors without a memory management unit place certain
|
||||
restrictions on the userspace programs. Here we will provide some guidelines
|
||||
for people who are not familiar with such systems.
|
||||
|
||||
If you are not familiar with virtual memory, you might want to review some
|
||||
background such as:
|
||||
http://en.wikipedia.org/wiki/Virtual_Memory
|
||||
/usr/src/linux/Documentation/nommu-mmap.txt
|
||||
|
||||
----------------------------
|
||||
--- No memory protection ---
|
||||
----------------------------
|
||||
|
||||
By virtue of every process getting its own virtual memory space, applications
|
||||
are protected from each other. So a bad memory access in one will not affect
|
||||
the memory of another. When processors forgo virtual memory, they typically
|
||||
do not add memory protection back in to the hardware. There are one or two
|
||||
exceptions to this rule, but for now, we'll assume no one supports it.
|
||||
|
||||
In practical terms, this means you cannot dereference bad pointers directly
|
||||
and expect the kernel to catch and kill your application. However, you can
|
||||
expect the kernel to catch some bad pointers when given to system calls.
|
||||
|
||||
For example, this will "work" in the sense that no signal will be sent:
|
||||
char *foo = NULL;
|
||||
foo[0] = 'a';
|
||||
foo[1] = 'b';
|
||||
|
||||
However, the kernel should return errors when using "standard" bad pointers
|
||||
with system calls. Such as:
|
||||
char *foo = NULL;
|
||||
write(1, foo, 10);
|
||||
-> kernel will return EFAULT or similar
|
||||
The other bad pointer you can rely on in your tests is -1:
|
||||
char *foo = (void *)-1;
|
||||
read(0, foo, 10);
|
||||
-> kernel will return EFAULT or similar
|
||||
|
||||
Otherwise, no bad pointer may reliably be tested, either directly or
|
||||
indirectly via the kernel. This tends to be a large part of the UCLINUX
|
||||
ifdef code that shows up in LTP.
|
||||
|
||||
----------------
|
||||
--- No forks ---
|
||||
----------------
|
||||
|
||||
The ubiquitous fork() function relies completely on the Copy On Write (COW)
|
||||
functionality provided by virtual memory to share pages between processes.
|
||||
Since this isn't feasible without virtual memory, there is no fork() function.
|
||||
You will either get a linker error (undefined reference to fork) or you will
|
||||
get a runtime failure of ENOSYS.
|
||||
|
||||
Typically, fork() is used for very few programming paradigms:
|
||||
- daemonization
|
||||
- run a program
|
||||
- parallelism
|
||||
|
||||
For the daemonization functionality, simply use the daemon() function. This
|
||||
works under both MMU and NOMMU systems.
|
||||
|
||||
To run a program, simply use vfork() followed by an exec-style function.
|
||||
And change the error handler in the child from exit() to _exit(). This too
|
||||
works under both MMU and NOMMU systems. But be aware of vfork() semantics --
|
||||
since the parent and child share the same memory process, the child has to be
|
||||
careful in what it does. This is why the recommended construct is simply:
|
||||
pid_t child = vfork();
|
||||
if (vfork == 0)
|
||||
_exit(execl(....));
|
||||
|
||||
For parallelism where processes use IPC to work together, you have to options,
|
||||
neither of which are easy. You can rewrite to use threads, or you can re-exec
|
||||
yourself with special flags to pass along updated runtime state. This is what
|
||||
the self_exec() helper function in LTP is designed for.
|
||||
|
||||
-------------------------
|
||||
--- No overcommitting ---
|
||||
-------------------------
|
||||
|
||||
Virtual memory allows people to do malloc(128MiB) and get back a buffer that
|
||||
big. But that buffer is only of virtual memory, not physical. On a NOMMU
|
||||
system, the memory comes immediately from physical memory and takes it away
|
||||
from anyone else.
|
||||
|
||||
Avoid large mallocs.
|
||||
|
||||
---------------------
|
||||
--- Fragmentation ---
|
||||
---------------------
|
||||
|
||||
On a MMU system, when physical memory gets fragmented, things slow down. But
|
||||
they keep working. This is because every new process gets a clean virtual
|
||||
memory address space. While processes can fragment their own virtual address
|
||||
space, this usually takes quite a long time and a lot of effort, so generally
|
||||
it is not a problem people hit.
|
||||
|
||||
On a NOMMU system, when physical memory gets fragmented, access to large
|
||||
contiguous blocks becomes unavailable which means requests fail. Even if your
|
||||
system has 40MiB _total_ free, the largest contiguous block might only be 1MiB
|
||||
which means that allocations larger than that will always fail.
|
||||
|
||||
Break up your large memory allocations when possible. Generally speaking,
|
||||
single allocations under 2MiB aren't a problem.
|
||||
|
||||
-----------------
|
||||
--- No paging ---
|
||||
-----------------
|
||||
|
||||
No virtual memory means you can't mmap() a file and only have the pages read in
|
||||
(paged) on the fly. So if you use mmap() on a file, the kernel must allocate
|
||||
memory for it and read in all the contents immediately.
|
||||
|
||||
---------------------
|
||||
--- No swap space ---
|
||||
---------------------
|
||||
|
||||
See the "No paging" section above. For the same reason, there is no support
|
||||
for swap partitions. Plus, nommu typically means embedded which means flash
|
||||
based storage which means limited storage space and limited number of times
|
||||
you can write it.
|
||||
|
||||
-------------------------
|
||||
--- No dynamic stacks ---
|
||||
-------------------------
|
||||
|
||||
No virtual memory means that applications can't all have their stacks at the
|
||||
top of memory and allowed to grown "indefinitely" downwards. Stack space is
|
||||
fixed at process creation time (when it is first executed) and cannot grow.
|
||||
While the fixed size may be increased, it's best to avoid stack pressure in
|
||||
the first place.
|
||||
|
||||
Avoid the alloca() function and use malloc()/free() instead.
|
||||
|
||||
Avoid declaring large buffers on the stack. Some people like to do things
|
||||
such as:
|
||||
char buf[PATH_MAX];
|
||||
This will most likely smash the stack on nommu systems ! Use global variables
|
||||
(the bss), or use malloc()/free() type functions.
|
||||
|
||||
-------------------------------
|
||||
--- No dynamic data segment ---
|
||||
-------------------------------
|
||||
|
||||
No virtual memory means that mappings cannot arbitrarily be extended. Another
|
||||
process might have its own mapping right after yours! This is where the brk()
|
||||
and sbrk() functions come into play. These are most often used to dynamically
|
||||
increase the heap space via the C library, but a few people use these manually.
|
||||
|
||||
Best if you simply avoid them, and if you're writing tests to exercise these
|
||||
functions specifically, make them nops/XFAIL for nommu systems.
|
||||
|
||||
-------------------------------
|
||||
--- Limited shared mappings ---
|
||||
-------------------------------
|
||||
|
||||
No virtual memory means files cannot be mmapped in and have writes to it
|
||||
written back out to disk on the fly. So you cannot use MAP_SHARED when
|
||||
mmapping a file.
|
||||
|
||||
-------------------------
|
||||
--- No fixed mappings ---
|
||||
-------------------------
|
||||
|
||||
The MAP_FIXED option to mmap() is not supported. It doesn't even really work
|
||||
all that well under MMU systems.
|
||||
|
||||
Best if you simply avoid it, and if you're writing tests to exercise this
|
||||
option specifically, make them nops/XFAIL for nommu systems.
|
||||
@@ -17,7 +17,6 @@ Let's start with an example, following code is a simple test for a 'getenv()'.
|
||||
[source,c]
|
||||
-------------------------------------------------------------------------------
|
||||
/*\
|
||||
* [Description]
|
||||
* Tests basic functionality of getenv().
|
||||
*
|
||||
* - create an env variable and verify that getenv() can get it
|
||||
@@ -94,26 +93,32 @@ in range of [0, '.tcnt' - 1].
|
||||
|
||||
IMPORTANT: Only one of '.test' and '.test_all' can be set at a time.
|
||||
|
||||
Each test has a limit on how long it can run and the limit composes of two
|
||||
parts max_runtime and timeout. The max_runtime is a limit for how long can the
|
||||
'.test_all' or a set of '.test' functions take and the timeout is static part
|
||||
that should cover the duration of test setup and cleanup plus some safety.
|
||||
Each test has a limit on how long it can run, composed of two parts: 'runtime'
|
||||
and 'timeout'. The 'runtime' is the limit for how long the '.test_all' or a set
|
||||
of '.test' main functions can execute. The 'timeout', on the other hand, applies
|
||||
to the total time for setup, single test function invocation, cleanup, and some
|
||||
additional safety margin. If test without an explicit 'runtime', the 'timeout'
|
||||
governs the entire test duration.
|
||||
|
||||
The timeout timer is also reset on each subsequent iteration with the test -i
|
||||
parameter, variants or .all_filesystems.
|
||||
|
||||
Any test that runs for more than a second or two has to make sure to:
|
||||
|
||||
- set the runtime either by setting the '.max_runtime' in tst_test or by
|
||||
calling 'tst_set_max_runtime()' in the test setup
|
||||
- set the runtime by setting '.runtime' in tst_test and calling 'tst_set_runtime()'
|
||||
to monitor the remaining runtime and ensure the test exits when the runtime
|
||||
limit is reached.
|
||||
|
||||
- monitor remaning runtime by regular calls to 'tst_remaining_runtime()' and
|
||||
exit when runtime has been used up
|
||||
- set the timeout by setting '.timeout' in tst_test to limit the whole test
|
||||
run that does not use 'tst_remaining_runtime()'.
|
||||
|
||||
Test is free to exit before max_runtime has been used up for example when
|
||||
Test is free to exit before runtime has been used up for example when
|
||||
minimal number of iteration was finished.
|
||||
|
||||
The limit is applied to a single call of the '.test_all' function that means
|
||||
that for example when '.test_variants' or '.all_filesystems' is set the whole
|
||||
test will be limited by 'variants * (max_runtime + timeout)' seconds and the
|
||||
test runtime will be likely close to 'variants * max_runtime' seconds.
|
||||
test will be limited by 'variants * (runtime + timeout)' seconds and the
|
||||
test runtime will be likely close to 'variants * runtime' seconds.
|
||||
|
||||
[source,c]
|
||||
-------------------------------------------------------------------------------
|
||||
@@ -224,10 +229,12 @@ void tst_res(int ttype, char *arg_fmt, ...);
|
||||
Printf-like function to report test result, it's mostly used with ttype:
|
||||
|
||||
|==============================
|
||||
| 'TPASS' | Test has passed.
|
||||
| 'TFAIL' | Test has failed.
|
||||
| 'TINFO' | General message.
|
||||
| 'TWARN' | Something went wrong but we decided to continue. Mostly used in cleanup functions.
|
||||
| 'TPASS' | Test has passed.
|
||||
| 'TFAIL' | Test has failed.
|
||||
| 'TINFO' | General message.
|
||||
| 'TDEBUG' | Debug message (new C API only, printed with '-D' or via 'LTP_ENABLE_DEBUG=1' or 'y'
|
||||
environment variable), only for messages which would be too verbose for normal run.
|
||||
| 'TWARN' | Something went wrong but we decided to continue. Mostly used in cleanup functions.
|
||||
|==============================
|
||||
|
||||
The 'ttype' can be combined bitwise with 'TERRNO' or 'TTERRNO' to print
|
||||
@@ -238,13 +245,13 @@ The 'ttype' can be combined bitwise with 'TERRNO' or 'TTERRNO' to print
|
||||
void tst_brk(int ttype, char *arg_fmt, ...);
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Printf-like function to report error and exit the test, it can be used with ttype:
|
||||
Printf-like function to report result and exits current test. If test uses
|
||||
'.all_filesystems', '.test_variants' etc. the 'tst_brk()' exits current test
|
||||
iteration e.g. currently running filesystem test or a test variant unless
|
||||
'ttype' is set to 'TBROK'.
|
||||
|
||||
|============================================================
|
||||
| 'TBROK' | Something has failed in test preparation phase.
|
||||
| 'TCONF' | Test is not appropriate for current configuration
|
||||
(syscall not implemented, unsupported arch, ...)
|
||||
|============================================================
|
||||
If 'ttype' is set to 'TBROK' all test processes are killed and the test exits
|
||||
immediately with an error.
|
||||
|
||||
The 'ttype' can be combined bitwise with 'TERRNO' or 'TTERRNO' to print
|
||||
'errno', 'TST_ERR' respectively.
|
||||
@@ -338,7 +345,7 @@ if (TST_RET > -1) {
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
The +TEST+ macro sets +TST_RET+ to its argument's return value and +TST_ERR+ to
|
||||
+errno+. The +TTERNO+ flag can be used to print the error number's symbolic
|
||||
+errno+. The +TTERRNO+ flag can be used to print the error number's symbolic
|
||||
value.
|
||||
|
||||
No LTP library function or macro, except those in 'tst_test_macros.h', will
|
||||
@@ -399,13 +406,25 @@ WARNING: This function is not thread safe.
|
||||
|
||||
[source,c]
|
||||
-------------------------------------------------------------------------------
|
||||
void tst_set_max_runtime(int max_runtime);
|
||||
void tst_set_timeout(int timeout);
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Allows for setting max_runtime per test iteration dynamically in the test 'setup()',
|
||||
the timeout is specified in seconds. There are a few testcases whose runtime
|
||||
can vary arbitrarily, these can disable timeouts by setting it to
|
||||
TST_UNLIMITED_RUNTIME.
|
||||
Allows for setting the entire timeout dynamically during the test setup(). The
|
||||
timeout is specified in seconds and represents the total time allowed for a single
|
||||
test iteration, including setup, runtime, and teardown phases.
|
||||
|
||||
[source,c]
|
||||
-------------------------------------------------------------------------------
|
||||
void tst_set_runtime(int runtime);
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Allows for setting the runtime per test iteration dynamically during the test 'setup()'.
|
||||
The runtime is specified in seconds and represents the duration the test is allowed
|
||||
to execute its main workload, excluding setup and teardown phases.
|
||||
|
||||
This function is useful for tests where the duration of the main workload can be
|
||||
controlled or needs to be adjusted dynamically. For example, tests that loop until
|
||||
the runtime expires can use this function to define how long they should run.
|
||||
|
||||
[source,c]
|
||||
-------------------------------------------------------------------------------
|
||||
@@ -628,15 +647,15 @@ IMPORTANT: You have to set the '.forks_child' flag in the test structure
|
||||
Results reported by 'tst_res()' are propagated to the parent test process via
|
||||
block of shared memory.
|
||||
|
||||
Calling 'tst_brk()' causes child process to exit with non-zero exit value.
|
||||
Which means that it's safe to use 'SAFE_*()' macros in the child processes as
|
||||
well.
|
||||
Calling 'tst_brk()' causes child process to set the test library abort flag and
|
||||
exits the test immediately. Which means that it's safe to use 'SAFE_*()' macros
|
||||
in the child processes as well.
|
||||
|
||||
Children that outlive the 'test()' function execution are waited for in the
|
||||
test library. Unclean child exit (killed by signal, non-zero exit value, etc.)
|
||||
will cause the main test process to exit with 'tst_brk()', which especially
|
||||
means that 'TBROK' propagated from a child process will cause the whole test
|
||||
to exit with 'TBROK'.
|
||||
will cause the main test process to exit with 'tst_brk()'. That means that all
|
||||
test child processes are supposed to exit with success unless they are
|
||||
explicitly waited for.
|
||||
|
||||
If a test needs a child that segfaults or does anything else that cause it to
|
||||
exit uncleanly all you need to do is to wait for such children from the
|
||||
@@ -1332,8 +1351,9 @@ return value is '255' if 'execvp()' failed with 'ENOENT' and '254' otherwise.
|
||||
'stdout_path' and 'stderr_path' determine where to redirect the program
|
||||
stdout and stderr I/O streams.
|
||||
|
||||
The 'SAFE_CMD()' macro can be used automatic handling non-zero exits (exits
|
||||
with 'TBROK') and 'ENOENT' (exits with 'TCONF').
|
||||
'SAFE_CMD()' is a wrapper for 'tst_cmd()' which can be used for automatic
|
||||
handling non-zero exit (exits with 'TBROK') and 'ENOENT' (the program not in
|
||||
'$PATH', exits with 'TCONF').
|
||||
|
||||
.Example
|
||||
[source,c]
|
||||
@@ -1631,7 +1651,7 @@ with 'TBROK'. This behavior can be changed using tst_path_val.flags:
|
||||
* 'TST_SR_TBROK_RO' – End test with 'TBROK' if the file is read-only
|
||||
* 'TST_SR_TCONF_RO' – End test with 'TCONF' if the file is read-only
|
||||
* 'TST_SR_SKIP_RO' – Continue without saving the file if it is read-only
|
||||
* 'TST_SR_IGNORE_ERR' – Ignore errors when writing new value into the file
|
||||
* 'TST_SR_IGNORE_ERR' – Ignore all errors during reading and writing the file
|
||||
|
||||
Common flag combinations also have shortcuts:
|
||||
|
||||
@@ -1812,7 +1832,7 @@ fault or EFAULT depending on if the access happened in userspace or the kernel
|
||||
respectively. The canary before the buffer will also catch any write access
|
||||
outside of the buffer.
|
||||
|
||||
The purpose of the patch is to catch off-by-one bugs which happens when
|
||||
The purpose of this feature is to catch off-by-one bugs which happens when
|
||||
buffers and structures are passed to syscalls. New tests should allocate
|
||||
guarded buffers for all data passed to the tested syscall which are passed by
|
||||
a pointer.
|
||||
@@ -2016,9 +2036,8 @@ static struct tst_test test = {
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
Above is a minimal template for a test using fuzzy-sync. In a simple case, you
|
||||
just need to put the bits you want to race inbetween 'start_race' and
|
||||
'end_race'. Meanwhile, any setup you need to do per-iteration goes outside the
|
||||
windows.
|
||||
just need to put the bits you want to race between 'start_race' and 'end_race'.
|
||||
Meanwhile, any setup you need to do per-iteration goes outside the windows.
|
||||
|
||||
Fuzzy sync synchronises 'run_a' and 'run_b', which act as barriers, so that
|
||||
neither thread can progress until the other has caught up with it. There is
|
||||
@@ -2336,7 +2355,7 @@ Some tests require at least size(MB) of free RAM or Swap.
|
||||
To make sure that test will run only on systems with more than minimal
|
||||
required amount of RAM set `.min_mem_avail = N`.
|
||||
|
||||
Similarily for tests that require certain amount of free Swap use
|
||||
Similarly for tests that require certain amount of free Swap use
|
||||
`.min_swap_avail = N`.
|
||||
|
||||
1.40 Test tags
|
||||
@@ -2424,6 +2443,25 @@ Test can be skipped on various conditions: on enabled SecureBoot
|
||||
('.skip_in_secureboot = 1'), lockdown ('.skip_in_lockdown = 1') or in 32-bit
|
||||
compat mode ('.skip_in_compat = 1').
|
||||
|
||||
1.43 Set resource limits
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
'.ulimit' allows to set resource limits on particular resource. NOTE: It sets 'rlim_max'
|
||||
only if it's higher than 'rlim_cur'.
|
||||
|
||||
[source,c]
|
||||
-------------------------------------------------------------------------------
|
||||
#include "tst_test.h"
|
||||
|
||||
static struct tst_test test = {
|
||||
...
|
||||
.ulimit = (const struct tst_ulimit_val[]) {
|
||||
{RLIMIT_STACK, RLIM_INFINITY},
|
||||
{}
|
||||
},
|
||||
};
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
2. Common problems
|
||||
------------------
|
||||
|
||||
@@ -143,7 +143,7 @@ static void setup(void)
|
||||
When opening a localhost socket isn't enough and the test needs special device
|
||||
or routing configuration, the netdevice library can create the required network
|
||||
setup without calling external programs. Internally, the netdevice functions
|
||||
use a rtnetlink socket to communicate with the kernel.
|
||||
use a netlink socket to communicate with the kernel.
|
||||
|
||||
All of these functions will call +tst_brk()+ on failure, unless stated
|
||||
otherwise. Error values described below are returned only during test cleanup
|
||||
@@ -274,12 +274,12 @@ static void setup(void)
|
||||
}
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
3 rtnetlink API
|
||||
---------------
|
||||
3 Netlink API
|
||||
-------------
|
||||
|
||||
+#include "tst_rtnetlink.h"+
|
||||
+#include "tst_netlink.h"+
|
||||
|
||||
The rtnetlink library provides helper functions for constructing and sending
|
||||
The netlink library provides helper functions for constructing and sending
|
||||
arbitrary messages and parsing kernel responses.
|
||||
|
||||
All of the functions below will call +tst_brk()+ on failure, unless stated
|
||||
@@ -291,16 +291,16 @@ stage.
|
||||
|
||||
[source,c]
|
||||
-------------------------------------------------------------------------------
|
||||
struct tst_rtnl_context;
|
||||
struct tst_netlink_context;
|
||||
|
||||
struct tst_rtnl_attr_list {
|
||||
struct tst_netlink_attr_list {
|
||||
unsigned short type;
|
||||
const void *data;
|
||||
ssize_t len;
|
||||
const struct tst_rtnl_attr_list *sublist;
|
||||
const struct tst_netlink_attr_list *sublist;
|
||||
};
|
||||
|
||||
struct tst_rtnl_message {
|
||||
struct tst_netlink_message {
|
||||
struct nlmsghdr *header;
|
||||
struct nlmsgerr *err;
|
||||
void *payload;
|
||||
@@ -308,17 +308,18 @@ struct tst_rtnl_message {
|
||||
};
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
+struct tst_rtnl_context+ is an opaque rtnetlink socket with buffer for
|
||||
+struct tst_netlink_context+ is an opaque netlink socket with buffer for
|
||||
constructing and sending arbitrary messages using the functions described
|
||||
below. Create a new context using +RTNL_CREATE_CONTEXT()+, then free it using
|
||||
+RTNL_DESTROY_CONTEXT()+ when you're done with it.
|
||||
below. Create a new context using +NETLINK_CREATE_CONTEXT()+, then free it
|
||||
using +NETLINK_DESTROY_CONTEXT()+ when you're done with it.
|
||||
|
||||
+struct tst_rtnl_attr_list+ is a helper structure for defining complex
|
||||
+struct tst_netlink_attr_list+ is a helper structure for defining complex
|
||||
rtnetlink message attribute payloads, including nested attribute lists. Every
|
||||
list and sublist defined using this structure is terminated by item with
|
||||
negative +len+.
|
||||
|
||||
- +type+ is the attribute type that will be stored in +struct rtattr.rta_type+.
|
||||
- +type+ is the attribute type that will be stored in +struct nlattr.nla_type+
|
||||
or +struct rtattr.rta_type+.
|
||||
|
||||
- +data+ contains arbitrary attribute payload.
|
||||
|
||||
@@ -326,15 +327,15 @@ negative +len+.
|
||||
set +len+ to 0. The last item in a list or sublist must have negative length.
|
||||
|
||||
- +sublist+ contains a nested attribute list which will be appended after
|
||||
+data+ as part of the attribute payload. +struct rtattr.rta_len+ will be
|
||||
calculated automatically with proper alignment, do _not_ add the sublist size
|
||||
to the +len+ field. If you do not want to add nested attributes, set
|
||||
+sublist+ to +NULL+.
|
||||
+data+ as part of the attribute payload. +struct nlattr.nla_len+ or
|
||||
+struct rtattr.rta_len+ will be calculated automatically with proper
|
||||
alignment, do _not_ add the sublist size to the +len+ field. If you do not
|
||||
want to add nested attributes, set +sublist+ to +NULL+.
|
||||
|
||||
+struct tst_rtnl_message+ is a structure holding partially parsed rtnetlink
|
||||
messages received from the kernel. +RTNL_RECV()+ returns an array of these
|
||||
+struct tst_netlink_message+ is a structure holding partially parsed netlink
|
||||
messages received from the kernel. +NETLINK_RECV()+ returns an array of these
|
||||
structures with the last item having +NULL+ in the +header+ field. Call
|
||||
+RTNL_FREE_MESSAGE()+ to free a message list returned by +RTNL_RECV()+.
|
||||
+NETLINK_FREE_MESSAGE()+ to free a message list returned by +NETLINK_RECV()+.
|
||||
|
||||
- +header+ is the netlink header structure of the message. +NULL+ in the header
|
||||
field terminates a list of messages.
|
||||
@@ -349,84 +350,110 @@ structures with the last item having +NULL+ in the +header+ field. Call
|
||||
3.2 Sending and receiving messages
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
- +struct tst_rtnl_context *RTNL_CREATE_CONTEXT(void)+ – Creates a new
|
||||
rtnetlink communication context for use with the functions described below.
|
||||
Returns +NULL+ on error.
|
||||
- +struct tst_netlink_context *NETLINK_CREATE_CONTEXT(int protocol)+ – Creates
|
||||
a new netlink communication context with given netlink protocol for use
|
||||
with the functions described below. Returns +NULL+ on error.
|
||||
|
||||
- +void RTNL_FREE_MESSAGE(struct tst_rtnl_message *msg)+ – Frees an array of
|
||||
messages returned by +RTNL_RECV()+.
|
||||
- +void NETLINK_FREE_MESSAGE(struct tst_netlink_message *msg)+ – Frees
|
||||
an array of messages returned by +NETLINK_RECV()+.
|
||||
|
||||
- +void RTNL_DESTROY_CONTEXT(struct tst_rtnl_context *ctx)+ – Closes a
|
||||
communication context created by +RTNL_CREATE_CONTEXT()+.
|
||||
- +void NETLINK_DESTROY_CONTEXT(struct tst_netlink_context *ctx)+ – Closes a
|
||||
communication context created by +NETLINK_CREATE_CONTEXT()+.
|
||||
|
||||
- +int RTNL_SEND(struct tst_rtnl_context *ctx)+ – Sends all messages waiting
|
||||
in +ctx+ buffer to the kernel. If there are multiple messages to send, a new
|
||||
+NLMSG_DONE+ message will be added automatically. Returns the number of
|
||||
bytes sent on success. Return 0 or negative value on error.
|
||||
- +int NETLINK_SEND(struct tst_netlink_context *ctx)+ – Sends all messages
|
||||
waiting in +ctx+ buffer to the kernel. If there are multiple messages
|
||||
to send, a new +NLMSG_DONE+ message will be added automatically. Returns
|
||||
the number of bytes sent on success. Return 0 or negative value on error.
|
||||
|
||||
- +int RTNL_SEND_VALIDATE(struct tst_rtnl_context *ctx)+ – Sends all messages
|
||||
just like +RTNL_SEND()+, then receives the response from the kernel and
|
||||
validates results of requests sent with the +NLM_F_ACK+ flag. This function
|
||||
calls +tst_brk()+ as usual if communication fails but it will return error
|
||||
status without terminating the test if one of the received messages contains
|
||||
error code. See +RTNL_CHECK_ACKS()+ below for explanation of the return
|
||||
value.
|
||||
- +int NETLINK_SEND_VALIDATE(struct tst_netlink_context *ctx)+ – Sends all
|
||||
messages just like +NETLINK_SEND()+, then receives the response from
|
||||
the kernel and validates results of requests sent with the +NLM_F_ACK+ flag.
|
||||
This function calls +tst_brk()+ as usual if communication fails but it will
|
||||
return error status without terminating the test if one of the received
|
||||
messages contains error code. See +NETLINK_CHECK_ACKS()+ below for
|
||||
explanation of the return value.
|
||||
|
||||
- +int RTNL_WAIT(struct tst_rtnl_context *ctx)+ – Waits until data becomes
|
||||
available to read from the rtnetlink socket (timeout: 1 second). Returns 1
|
||||
- +int NETLINK_WAIT(struct tst_netlink_context *ctx)+ – Waits until data becomes
|
||||
available to read from the netlink socket (timeout: 1 second). Returns 1
|
||||
if there is data to read, 0 on timeout or -1 on error.
|
||||
|
||||
- +struct tst_rtnl_message *RTNL_RECV(struct tst_rtnl_context *ctx)+ – Receives
|
||||
rtnetlink messages from the kernel. The messages are received in non-blocking
|
||||
mode so calling +RTNL_WAIT()+ first is recommended. Returns an array of
|
||||
partially parsed messages terminated by an item with +NULL+ in the +header+
|
||||
field. On error or when there are no messages to receive, returns +NULL+.
|
||||
Call +RTNL_FREE_MESSAGE()+ to free the returned data.
|
||||
- +struct tst_netlink_message *NETLINK_RECV(struct tst_netlink_context *ctx)+ –
|
||||
Receives netlink messages from the kernel. The messages are received
|
||||
in non-blocking mode so calling +NETLINK_WAIT()+ first is recommended.
|
||||
Returns an array of partially parsed messages terminated by an item with
|
||||
+NULL+ in the +header+ field. On error or when there are no messages
|
||||
to receive, returns +NULL+. Call +NETLINK_FREE_MESSAGE()+ to free
|
||||
the returned data.
|
||||
|
||||
- +int RTNL_CHECK_ACKS(struct tst_rtnl_context *ctx, struct tst_rtnl_message
|
||||
*response)+ – Validate results of requests sent with the +NLM_F_ACK+ flag.
|
||||
Do not call +RTNL_ADD_MESSAGE()+ between +RTNL_SEND()+ and
|
||||
+RTNL_CHECK_ACKS()+ because it will reset the state of +ctx+ and prevent
|
||||
result validation. Returns 1 if all messages sent with the +NLM_F_ACK+ flag
|
||||
have a corresponding message in +response+ and the error code is 0. If any
|
||||
of the expected response messages is missing, this function will call
|
||||
+tst_brk()+ (or return 0 during test cleanup phase). If any of the response
|
||||
messages has non-zero error code, this function will return 0 and store the
|
||||
first non-zero error code in global variable +tst_rtnl_errno+ (sign-flipped
|
||||
just like regular libc +errno+).
|
||||
- +int NETLINK_CHECK_ACKS(struct tst_netlink_context *ctx,
|
||||
struct tst_netlink_message *response)+ – Validate results of requests sent
|
||||
with the +NLM_F_ACK+ flag. Do not call +NETLINK_ADD_MESSAGE()+ between
|
||||
+NETLINK_SEND()+ and +NETLINK_CHECK_ACKS()+ because it will reset the state
|
||||
of +ctx+ and prevent result validation. Returns 1 if all messages sent
|
||||
with the +NLM_F_ACK+ flag have a corresponding message in +response+ and
|
||||
the error code is 0. If any of the expected response messages is missing,
|
||||
this function will call +tst_brk()+ (or return 0 during test cleanup phase).
|
||||
If any of the response messages has non-zero error code, this function will
|
||||
return 0 and store the first non-zero error code in global variable
|
||||
+tst_netlink_errno+ (sign-flipped just like regular libc +errno+).
|
||||
|
||||
3.3 Creating messages
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
- +int RTNL_ADD_MESSAGE(struct tst_rtnl_context *ctx, const struct nlmsghdr
|
||||
*header, const void *payload, size_t payload_size)+ – Adds new rtnetlink
|
||||
message to +ctx+ buffer. You need to provide message +header+ and optional
|
||||
+payload+. +payload_size+ is the size of +payload+ data in bytes. If you
|
||||
don't want to add any payload data, set +payload+ to +NULL+ and
|
||||
- +int NETLINK_ADD_MESSAGE(struct tst_netlink_context *ctx, const struct
|
||||
nlmsghdr *header, const void *payload, size_t payload_size)+ – Adds new
|
||||
netlink message to +ctx+ buffer. You need to provide message +header+ and
|
||||
optional +payload+. +payload_size+ is the size of +payload+ data in bytes.
|
||||
If you don't want to add any payload data, set +payload+ to +NULL+ and
|
||||
+payload_size+ to 0. This function will automatically fill the +nlmsg_len+,
|
||||
+nlmsg_seq+ and +nlmsg_pid+ fields of the new message header. You don't need
|
||||
to set those. It'll also automatically add +NLM_F_MULTI+ flag when needed.
|
||||
Returns 1 on success, 0 on error. Note that the first call of
|
||||
+RTNL_ADD_MESSAGE()+ after +RTNL_SEND()+ will reset the state of +ctx+
|
||||
and +RTNL_CHECK_ACKS()+ will not work correctly until the next +RTNL_SEND()+.
|
||||
+NETLINK_ADD_MESSAGE()+ after +NETLINK_SEND()+ will reset the state of +ctx+
|
||||
and +NETLINK_CHECK_ACKS()+ will not work correctly until the next
|
||||
+NETLINK_SEND()+.
|
||||
|
||||
- +int RTNL_ADD_ATTR(struct tst_rtnl_context *ctx, unsigned short type, const
|
||||
void *data, unsigned short len)+ – Adds new attribute to the last message
|
||||
in +ctx+ buffer. See +RTNL_ADD_MESSAGE()+. You need to provide attribute
|
||||
+type+ which will be stored in +struct rtattr.rta_type+, optional payload
|
||||
+data+ and payload size +len+ in bytes. If you don't want to add any payload,
|
||||
set +data+ to +NULL+ and +len+ to 0. Returns 1 on success, 0 on error.
|
||||
- +int NETLINK_ADD_ATTR(struct tst_netlink_context *ctx, unsigned short type,
|
||||
const void *data, unsigned short len)+ – Adds new +struct nlattr+ attribute
|
||||
to the last message in +ctx+ buffer. See +NETLINK_ADD_MESSAGE()+. You need
|
||||
to provide attribute +type+ which will be stored in +struct nlattr.nla_type+,
|
||||
optional payload +data+ and payload size +len+ in bytes. If you don't want
|
||||
to add any payload, set +data+ to +NULL+ and +len+ to 0. Returns 1 on
|
||||
success, 0 on error.
|
||||
|
||||
- +int RTNL_ADD_ATTR_STRING(struct tst_rtnl_context *ctx, unsigned short type,
|
||||
const char *data)+ – Adds new string attribute to the last message in +ctx+
|
||||
buffer. Parameters and return value are the same as for +RTNL_ADD_ATTR()+,
|
||||
except the payload length is calculated using +strlen()+.
|
||||
- +int NETLINK_ADD_ATTR_STRING(struct tst_netlink_context *ctx, unsigned short
|
||||
type, const char *data)+ – Adds new +struct nlattr+ string attribute to the
|
||||
last message in +ctx+ buffer. Parameters and return value are the same as
|
||||
for +NETLINK_ADD_ATTR()+, except the payload length is calculated using
|
||||
+strlen()+.
|
||||
|
||||
- +int RTNL_ADD_ATTR_LIST(struct tst_rtnl_context *ctx, const struct
|
||||
tst_rtnl_attr_list *list)+ – Adds a list of attributes to the last message
|
||||
in +ctx+ buffer. See description of +struct tst_rtnl_attr_list+ and
|
||||
+RTNL_ADD_MESSAGE()+ above. Returns the number of added attributes on
|
||||
success (nested attributes are not counted), -1 on error.
|
||||
- +int NETLINK_ADD_ATTR_LIST(struct tst_netlink_context *ctx, const struct
|
||||
tst_netlink_attr_list *list)+ – Adds a list of +struct nlattr+ attributes
|
||||
to the last message in +ctx+ buffer. See description of
|
||||
+struct tst_netlink_attr_list+ and +NETLINK_ADD_MESSAGE()+ above. Returns
|
||||
the number of added attributes on success (nested attributes are not
|
||||
counted), -1 on error.
|
||||
|
||||
- +int RTNL_ADD_ATTR(struct tst_netlink_context *ctx, unsigned short type,
|
||||
const void *data, unsigned short len)+ – Adds new +struct rtattr+ attribute
|
||||
to the last message in +ctx+ buffer. See +NETLINK_ADD_MESSAGE()+. You need
|
||||
to provide attribute +type+ which will be stored in +struct rtattr.rta_type+,
|
||||
optional payload +data+ and payload size +len+ in bytes. If you don't want
|
||||
to add any payload, set +data+ to +NULL+ and +len+ to 0. Returns 1 on
|
||||
success, 0 on error.
|
||||
|
||||
- +int RTNL_ADD_ATTR_STRING(struct tst_netlink_context *ctx, unsigned short
|
||||
type, const char *data)+ – Adds new +struct rtattr+ string attribute to the
|
||||
last message in +ctx+ buffer. Parameters and return value are the same as
|
||||
for +RTNL_ADD_ATTR()+, except the payload length is calculated using
|
||||
+strlen()+.
|
||||
|
||||
- +int RTNL_ADD_ATTR_LIST(struct tst_netlink_context *ctx, const struct
|
||||
tst_netlink_attr_list *list)+ – Adds a list of +struct rtattr+ attributes
|
||||
to the last message in +ctx+ buffer. See description of
|
||||
+struct tst_netlink_attr_list+ and +NETLINK_ADD_MESSAGE()+ above. Returns
|
||||
the number of added attributes on success (nested attributes are not
|
||||
counted), -1 on error.
|
||||
|
||||
Example Usage
|
||||
+++++++++++++
|
||||
@@ -440,14 +467,14 @@ Example Usage
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include "tst_test.h"
|
||||
#include "tst_rtnetlink.h"
|
||||
#include "tst_netlink.h"
|
||||
#include "tst_netdevice.h"
|
||||
|
||||
...
|
||||
|
||||
void setup(void)
|
||||
{
|
||||
struct tst_rtnl_context *ctx;
|
||||
struct tst_netlink_context *ctx;
|
||||
int index, ret;
|
||||
in_addr_t addr;
|
||||
|
||||
@@ -465,12 +492,12 @@ void setup(void)
|
||||
index = NETDEV_INDEX_BY_NAME("ltp_veth1");
|
||||
info.ifa_index = index;
|
||||
|
||||
ctx = RTNL_CREATE_CONTEXT();
|
||||
RTNL_ADD_MESSAGE(ctx, &header, &info, sizeof(info));
|
||||
ctx = NETLINK_CREATE_CONTEXT(NETLINK_ROUTE);
|
||||
NETLINK_ADD_MESSAGE(ctx, &header, &info, sizeof(info));
|
||||
addr = inet_addr("192.168.123.45");
|
||||
RTNL_ADD_ATTR(ctx, IFA_LOCAL, &addr, sizeof(addr));
|
||||
ret = RTNL_SEND_VALIDATE(ctx);
|
||||
RTNL_DESTROY_CONTEXT(ctx);
|
||||
ret = NETLINK_SEND_VALIDATE(ctx);
|
||||
NETLINK_DESTROY_CONTEXT(ctx);
|
||||
|
||||
if (!ret) {
|
||||
tst_brk(TBROK, "Failed to set ltp_veth1 address");
|
||||
@@ -188,7 +188,7 @@ space as default value is used. Of course, it's possible to use separate functio
|
||||
1.2 Library environment variables and functions for shell
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Similarily to the C library various checks and preparations can be requested
|
||||
Similarly to the C library various checks and preparations can be requested
|
||||
simply by setting right '$TST_FOO'.
|
||||
|
||||
[options="header"]
|
||||
Executable → Regular
@@ -0,0 +1,7 @@
|
||||
# Use the same sphinx as on readthedocs.org. When updated, make sure
|
||||
# sphinx-rtd-theme is compatible with sphinx.
|
||||
sphinx==7.2.6
|
||||
sphinx-rtd-theme==2.0.0
|
||||
|
||||
linuxdoc==20231020
|
||||
sphinxcontrib-spelling==7.7.0
|
||||
@@ -1,6 +0,0 @@
|
||||
ID DESCRIPTION
|
||||
LTP-001 Library source files have tst_ prefix
|
||||
LTP-002 TST_RET and TST_ERR are never modified by test library functions
|
||||
LTP-003 Externally visible library symbols have the tst_ prefix
|
||||
LTP-004 Test executable symbols are marked static
|
||||
LTP-005 Array must terminate with a sentinel value (i.e. NULL or '{}')
|
||||
|
@@ -0,0 +1,161 @@
|
||||
aarch
|
||||
akpm
|
||||
amd
|
||||
archiver
|
||||
archs
|
||||
args
|
||||
asciidoc
|
||||
autoconf
|
||||
automake
|
||||
backport
|
||||
baz
|
||||
btime
|
||||
bufs
|
||||
CCed
|
||||
cgroup
|
||||
cgroups
|
||||
checksum
|
||||
checksums
|
||||
cmds
|
||||
codebase
|
||||
compat
|
||||
config
|
||||
cpus
|
||||
ctrls
|
||||
datafiles
|
||||
dependants
|
||||
dev
|
||||
devfs
|
||||
dio
|
||||
distro
|
||||
distros
|
||||
docparse
|
||||
doio
|
||||
executables
|
||||
fd
|
||||
filesystem
|
||||
filesystems
|
||||
fixup
|
||||
fs
|
||||
fstrict
|
||||
fuzzsync
|
||||
gcc
|
||||
gdb
|
||||
github
|
||||
gitignore
|
||||
glibc
|
||||
growfiles
|
||||
hugepage
|
||||
iogen
|
||||
kbuild
|
||||
kconfigs
|
||||
kver
|
||||
ld
|
||||
le
|
||||
libc
|
||||
libltp
|
||||
libs
|
||||
linkable
|
||||
linux
|
||||
lockdown
|
||||
ltp
|
||||
lwn
|
||||
Maipo
|
||||
Makefile
|
||||
Makefiles
|
||||
mem
|
||||
mnt
|
||||
mntpoint
|
||||
msg
|
||||
namespace
|
||||
namespaces
|
||||
onwards
|
||||
openSUSE
|
||||
patchset
|
||||
pkgconf
|
||||
posix
|
||||
ppc
|
||||
pre
|
||||
pre
|
||||
preprocessor
|
||||
rebase
|
||||
reflog
|
||||
reinit
|
||||
repo
|
||||
rofs
|
||||
runtest
|
||||
scall
|
||||
secureboot
|
||||
sourceware
|
||||
statx
|
||||
stdout
|
||||
structs
|
||||
stx
|
||||
subdirectory
|
||||
subshell
|
||||
subshells
|
||||
syscall
|
||||
syscalls
|
||||
tcnt
|
||||
tconf
|
||||
teardown
|
||||
testcase
|
||||
testcases
|
||||
testsuite
|
||||
testsuites
|
||||
tmp
|
||||
tmpdir
|
||||
toolchain
|
||||
toolchains
|
||||
torvalds
|
||||
tst
|
||||
uClibc
|
||||
ulimit
|
||||
un
|
||||
userland
|
||||
userspace
|
||||
vCPU
|
||||
vCPUs
|
||||
vendoring
|
||||
vger
|
||||
wallclock
|
||||
pid
|
||||
TBROK
|
||||
mkfs
|
||||
hugepages
|
||||
hugetlbfs
|
||||
printf
|
||||
scanf
|
||||
argv
|
||||
argc
|
||||
pthread
|
||||
futex
|
||||
hdr
|
||||
brk
|
||||
iovec
|
||||
iov
|
||||
strdup
|
||||
aprintf
|
||||
alloc
|
||||
hexd
|
||||
tcases
|
||||
strsig
|
||||
strstatus
|
||||
strerrno
|
||||
libcap
|
||||
capset
|
||||
capget
|
||||
musl
|
||||
setrlimit
|
||||
rlim
|
||||
optstr
|
||||
tmpfs
|
||||
nodev
|
||||
sys
|
||||
proc
|
||||
arg
|
||||
ver
|
||||
bitwise
|
||||
dereferenced
|
||||
allocator
|
||||
ptr
|
||||
@@ -0,0 +1,127 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
Installation and tests execution
|
||||
================================
|
||||
|
||||
Basics requirements to build LTP are the following:
|
||||
|
||||
* git
|
||||
* autoconf
|
||||
* automake
|
||||
* make
|
||||
* gcc
|
||||
* m4
|
||||
* pkgconf / pkg-config
|
||||
* libc headers
|
||||
* linux headers
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
$ git clone --recurse-submodules https://github.com/linux-test-project/ltp.git
|
||||
$ cd ltp
|
||||
$ make autotools
|
||||
$ ./configure
|
||||
|
||||
.. note::
|
||||
|
||||
For optional library dependencies, take a look at the scripts inside :master:`ci/`
|
||||
directory.
|
||||
|
||||
Running single tests
|
||||
--------------------
|
||||
|
||||
LTP provides the possibility to build and run single tests:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
$ cd testcases/kernel/syscalls/foo
|
||||
$ make
|
||||
$ PATH=$PATH:$PWD ./foo01
|
||||
|
||||
Shell testcases are a bit more complicated, since they need to setup ``PATH``
|
||||
as well as to compiled binary helpers:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
$ cd testcases/lib
|
||||
$ make
|
||||
$ cd ../commands/foo
|
||||
$ PATH=$PATH:$PWD:$PWD/../../lib/ ./foo01.sh
|
||||
|
||||
Open Posix Testsuite has it's own build system which needs Makefiles to be
|
||||
generated first:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
$ ./configure --with-open-posix-testsuite
|
||||
$ cd testcases/open_posix_testsuite/
|
||||
$ make generate-makefiles
|
||||
$ cd conformance/interfaces/foo
|
||||
$ make
|
||||
$ ./foo_1-1.run-test
|
||||
|
||||
Compiling and installing all testcases
|
||||
--------------------------------------
|
||||
|
||||
To compile all tests is really simple:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
$ make
|
||||
|
||||
$ # install LTP inside /opt/ltp by default
|
||||
$ make install
|
||||
|
||||
.. note::
|
||||
|
||||
Some tests will be disabled if ``configure`` script won't find the build
|
||||
dependencies.
|
||||
|
||||
Running tests
|
||||
-------------
|
||||
|
||||
To run all the test suites
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
$ cd /opt/ltp
|
||||
|
||||
$ # run syscalls testing suite
|
||||
$ ./kirk -U ltp -f syscalls
|
||||
|
||||
.. note::
|
||||
|
||||
Many test cases have to be executed as root.
|
||||
|
||||
Test suites (e.g. syscalls) are defined in the ``runtest`` directory. Each file
|
||||
contains a list of test cases in a simple format.
|
||||
|
||||
Each test case has its own executable or script that can directly executed:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
$ testcases/bin/abort01
|
||||
|
||||
$ # some tests have arguments
|
||||
$ testcases/bin/mesgq_nstest -m none
|
||||
|
||||
$ # vast majority of tests have a help
|
||||
$ testcases/bin/ioctl01 -h
|
||||
|
||||
$ # Many require certain environment variables to be set
|
||||
$ LTPROOT=/opt/ltp PATH="$PATH:$LTPROOT/testcases/bin" testcases/bin/wc01.sh
|
||||
|
||||
Most commonly, the ``PATH`` variable needs to be set and also ``LTPROOT``, but
|
||||
there are a number of other variables which usually ``kirk`` sets for you.
|
||||
|
||||
.. note::
|
||||
|
||||
All shell scripts need the ``PATH`` to be set. However, this is not limited
|
||||
to shell scripts and some C based tests need environment variables as well.
|
||||
They usually raise a configuration error when this is needed.
|
||||
|
||||
Network tests
|
||||
-------------
|
||||
|
||||
Network tests usually require a certain setup that is described in
|
||||
:master:`testcases/network/README.md`.
|
||||
@@ -0,0 +1,120 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
Tests setup
|
||||
===========
|
||||
|
||||
The internal LTP library provides a set of features that permits to customize
|
||||
tests behavior by setting environment variables and using specific tests
|
||||
arguments.
|
||||
|
||||
Library environment variables
|
||||
-----------------------------
|
||||
|
||||
Following environment variables are expected to be set by LTP users. Therefore,
|
||||
with some exceptions, they have ``LTP_`` prefix. Environment variables with
|
||||
``TST_`` prefix are used inside LTP shell API and should **not** be set by
|
||||
users.
|
||||
|
||||
.. list-table::
|
||||
:header-rows: 1
|
||||
|
||||
* - Variable
|
||||
- Note
|
||||
|
||||
* - KCONFIG_PATH
|
||||
- The path to the kernel config file, (if not set, it tries the usual paths
|
||||
``/boot/config-RELEASE`` or ``/proc/config.gz``)
|
||||
|
||||
* - KCONFIG_SKIP_CHECK
|
||||
- Skip kernel config check if variable set (not set by default)
|
||||
|
||||
* - LTPROOT
|
||||
- Prefix for installed LTP. **Should be always set**, since some tests
|
||||
need it to use data files (``LTP_DATAROOT``). LTP is by default installed
|
||||
into ``/opt/ltp``
|
||||
|
||||
* - LTP_COLORIZE_OUTPUT
|
||||
- By default LTP colorizes it's output unless it's redirected to a pipe or
|
||||
file. Force colorized output behavior: ``y`` or ``1``: always colorize,
|
||||
``n`` or ``0``: never colorize.
|
||||
|
||||
* - LTP_DEV
|
||||
- Path to the block device to be used. C Language: ``.needs_device = 1``.
|
||||
Shell language: ``TST_NEEDS_DEVICE=1``.
|
||||
|
||||
* - LTP_REPRODUCIBLE_OUTPUT
|
||||
- When set to ``1`` or ``y`` discards the actual content of the messages
|
||||
printed by the test (suitable for a reproducible output).
|
||||
|
||||
* - LTP_SINGLE_FS_TYPE
|
||||
- Specifies single filesystem to run the test on instead all supported
|
||||
(for tests with ``.all_filesystems``).
|
||||
|
||||
* - LTP_FORCE_SINGLE_FS_TYPE
|
||||
- Testing only. Behaves like LTP_SINGLE_FS_TYPE but ignores test skiplists.
|
||||
|
||||
* - LTP_DEV_FS_TYPE
|
||||
- Filesystem used for testing (default: ``ext2``).
|
||||
|
||||
* - LTP_TIMEOUT_MUL
|
||||
- Multiplies timeout, must be number >= 0.1 (> 1 is useful for slow
|
||||
machines to avoid unexpected timeout). It's mainly for shell API, which
|
||||
does not have LTP_RUNTIME_MUL. In C API it scales the default 30 sec
|
||||
safety margin, probably LTP_RUNTIME_MUL should be used instead.
|
||||
|
||||
* - LTP_RUNTIME_MUL
|
||||
- Multiplies maximal test iteration runtime. Tests that run for more than a
|
||||
second or two are capped on runtime. You can scale the default runtime
|
||||
both up and down with this multiplier. This is not yet implemented in the
|
||||
shell API.
|
||||
|
||||
* - LTP_IMA_LOAD_POLICY
|
||||
- Load IMA example policy, see :master:`testcases/kernel/security/integrity/ima/README.md`.
|
||||
|
||||
* - LTP_VIRT_OVERRIDE
|
||||
- Overrides virtual machine detection in the test library. Setting it to
|
||||
empty string, tells the library that system is not a virtual machine.
|
||||
Other possible values are ``kvm``, ``xen``, ``zvm`` and ``microsoft``
|
||||
that describe different types supervisors.
|
||||
|
||||
* - PATH
|
||||
- It's required to adjust path: ``PATH="$PATH:$LTPROOT/testcases/bin"``
|
||||
|
||||
* - TMPDIR
|
||||
- Base directory for template directory (C language: ``.needs_tmpdir = 1``
|
||||
and shell: ``TST_NEEDS_TMPDIR=1``). Must be an absolute path (default:
|
||||
'/tmp').
|
||||
|
||||
* - LTP_NO_CLEANUP
|
||||
- Disable running test cleanup (defined in ``TST_CLEANUP``).
|
||||
Shell API only.
|
||||
|
||||
* - LTP_ENABLE_DEBUG
|
||||
- Enable debug info (value ``1`` or ``y``). Equivalent of ``-D`` parameter.
|
||||
|
||||
Environment variables for network tests
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
See :master:`testcases/network/README.md`.
|
||||
|
||||
Test execution time and timeout
|
||||
-------------------------------
|
||||
|
||||
The limit on how long a test can run does compose of two parts: ``runtime``
|
||||
and ``timeout``. The limit does apply to a single test variant. That means, for
|
||||
example, that tests which run for all available filesystems will apply this
|
||||
limit for a single filesystem only.
|
||||
|
||||
The ``runtime`` is a cap on how long the ``run()`` function can take and for
|
||||
most testcases this part is set to zero. For tests that do run for more than a
|
||||
second or two the ``runtime`` has to be defined and the ``run()`` function
|
||||
has to check actively how much runtime is left.
|
||||
|
||||
Test runtime can be scaled up and down with ``LTP_RUNTIME_MUL`` environment
|
||||
variable or set on a command-line by the ``-I`` parameter. However,
|
||||
setting the runtime too low will cause long running tests to exit prematurely,
|
||||
possibly before having a chance to actually test anything.
|
||||
|
||||
The timeout is a limit for test setup and cleanup and it's also a safety
|
||||
margin for the runtime accounting. It's currently set to 30 seconds but it may
|
||||
change later. If your target machine is too slow, it can be scaled up with the
|
||||
``LTP_TIMEOUT_MUL`` environment variable.
|
||||
@@ -0,0 +1,9 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
Statistics
|
||||
==========
|
||||
|
||||
In this section we collect some statistics related to the current state of
|
||||
LTP tests.
|
||||
|
||||
.. include:: ../_static/syscalls.rst
|
||||
@@ -0,0 +1,114 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
Supported systems
|
||||
=================
|
||||
|
||||
LTP `master <https://github.com/linux-test-project/ltp/commits/master>`_
|
||||
branch is build tested in
|
||||
`GitHub Actions <https://github.com/linux-test-project/ltp/actions>`_.
|
||||
|
||||
.. note::
|
||||
|
||||
There is no CI for the actual test runs.
|
||||
|
||||
Kernel version
|
||||
--------------
|
||||
|
||||
Minimal supported kernel version is **4.4**.
|
||||
|
||||
Oldest build tested distributions
|
||||
---------------------------------
|
||||
|
||||
.. list-table::
|
||||
:header-rows: 1
|
||||
|
||||
* - Distro
|
||||
- Kernel
|
||||
- glibc
|
||||
- gcc
|
||||
- clang
|
||||
|
||||
* - openSUSE Leap 42.2
|
||||
- 4.4
|
||||
- 2.22
|
||||
- 4.8.5
|
||||
- \-
|
||||
|
||||
* - Ubuntu 18.04 LTS bionic
|
||||
- 4.15
|
||||
- 2.27
|
||||
- 7.3.0
|
||||
- \-
|
||||
|
||||
* - Debian 11 (bullseye)
|
||||
- 5.10
|
||||
- 2.31
|
||||
- 10.2.1
|
||||
- 11.0.1
|
||||
|
||||
For a full list of build tested distros, please check :master:`.github/workflows/ci-docker-build.yml`.
|
||||
|
||||
Older distributions are not officially supported, which means that it
|
||||
may or may not work. It all depends on your luck. It should be possible
|
||||
to compile latest LTP even on slightly older distributions than we
|
||||
support with a few manual tweaks, e.g. disabling manually tests for
|
||||
newly added syscalls, etc. **Trivial fixes/workarounds may be accepted,
|
||||
but users are encouraged to move to a newer distro.**
|
||||
|
||||
If latest LTP cannot be compiled even with some amount of workarounds,
|
||||
you may result to older LTP releases, however these are **not** supported
|
||||
in any way. Also if you are trying to run LTP on more than 10 years old
|
||||
distribution you may as well reconsider you life choices.
|
||||
|
||||
Build tested architectures
|
||||
--------------------------
|
||||
|
||||
.. list-table::
|
||||
:header-rows: 1
|
||||
|
||||
* - Architecture
|
||||
- Build
|
||||
|
||||
* - x86_64
|
||||
- native
|
||||
|
||||
* - x86 emulation
|
||||
- native
|
||||
|
||||
* - aarch64
|
||||
- cross compilation
|
||||
|
||||
* - ppc64le
|
||||
- cross compilation
|
||||
|
||||
* - s390x
|
||||
- cross compilation
|
||||
|
||||
Supported C libraries
|
||||
---------------------
|
||||
|
||||
.. list-table::
|
||||
:header-rows: 1
|
||||
|
||||
* - C library
|
||||
- Note
|
||||
|
||||
* - `glibc <https://www.gnu.org/software/libc/>`_
|
||||
- Targeted libc, tested both compilation and actual test results.
|
||||
|
||||
* - `uClibc-ng <https://uclibc-ng.org/>`_
|
||||
- Although not being tested, it should work as it attempt to maintain a glibc compatible interface.
|
||||
|
||||
* - `uClibc <https://www.uclibc.org/>`_
|
||||
- Older uClibc might have problems.
|
||||
|
||||
* - `musl <https://musl.libc.org/>`_
|
||||
- Not yet fully supported. Check :master:`ci/alpine.sh` script.
|
||||
|
||||
* - Android
|
||||
- Please use `AOSP fork <https://android.googlesource.com/platform/external/ltp>`_.
|
||||
|
||||
C version
|
||||
---------
|
||||
|
||||
LTP is compiled with ``-std=gnu99``.
|
||||
@@ -0,0 +1,7 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
Test catalog
|
||||
============
|
||||
|
||||
.. include:: ../_static/tests.rst
|
||||
|
||||
@@ -0,0 +1,155 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
Testers guide to the Linux test project
|
||||
=======================================
|
||||
|
||||
While we try to make LTP work out of the box as much as possible there are
|
||||
still many things that testers need to consider before the actual testing
|
||||
starts. It's advisable to make a test plan in order to asses and formalize the
|
||||
expected test coverage or even just sit down for a while and consider different
|
||||
aspects of the problem at hand.
|
||||
|
||||
|
||||
Is testing even required?
|
||||
-------------------------
|
||||
|
||||
Some may argue that testing the Linux kernel locally is unnecessary because it
|
||||
is already thoroughly tested upstream and considered stable. While it's true
|
||||
that upstream releases generally go through extensive validation, including
|
||||
test suites like LTP, stability is only guaranteed when you use the upstream
|
||||
kernel sources and configuration exactly as released.
|
||||
|
||||
This assumption breaks down once you apply any changes: whether that's
|
||||
modifying the source code, enabling/disabling different `.config` options, or
|
||||
backporting patches. Such changes can introduce subtle bugs or unintended
|
||||
behavior, even if the upstream kernel is stable.
|
||||
|
||||
For example, backporting patches without their full dependency chain can lead
|
||||
to unexpected regressions. Therefore, it’s crucial to test your own kernel
|
||||
builds in the environment where they will actually run, using tools like LTP to
|
||||
catch issues that does not exists or are not triggered in the upstream
|
||||
configuration.
|
||||
|
||||
|
||||
Multi dimensionality
|
||||
--------------------
|
||||
|
||||
First of all kernel testing is a multi dimensional problem, just compiling and
|
||||
running LTP will give you some coverage but very likely not enough. There are
|
||||
several big gaps that may be easily missed.
|
||||
|
||||
For example 64bit Linux kernel provides compatibility layer for 32bit
|
||||
applications whose code quality is usually a bit worse than the 64bit ABI.
|
||||
Hence recompiling LTP with `-m32` in compiler flags and running both 64bit and
|
||||
32bit test binaries is a good start. If you try to make an argument that your
|
||||
application does not need 32bit support it's better to disable the compat layer
|
||||
completely since it's possible source of security bugs.
|
||||
|
||||
Another dimension is the number of architectures you need to test, for a
|
||||
general distribution testing you may end up with a couple of them. Different
|
||||
architectures have different platform code as well as differences in memory
|
||||
orderings, etc. that all means that running tests on one architecture out of
|
||||
several will give you incomplete coverage.
|
||||
|
||||
Since most of the POSIX API deals with files, the choice of filesystem for the
|
||||
testing changes the focus and coverage too. LTP defaults to using `/tmp/` as a
|
||||
temporary directory for the tests. If `/tmp/` is mounted as tmpfs subset of
|
||||
tests will be skipped, if that is the case it's advisable to point environment
|
||||
variable `TMPDIR` to a path with a different filesystem instead. Then there are
|
||||
tests that format a device with a filesystem. LTP defaults to `ext2` and loop
|
||||
devices for these testcases, that can be changed with environment variables as
|
||||
well. Lastly but not least a few testcases repeat the test for all supported
|
||||
filesystem, if you are interested in testing on a single filesystem only, you
|
||||
can limit these tests to a single filesystem too. See the tests setup for a
|
||||
comprehensive list of the `evironment variables
|
||||
<setup_tests.html#library-environment-variables>`_.
|
||||
|
||||
Then you also have to decide if you are going to run tests in virtual machine
|
||||
e.g. `qemu-kvm`, on bare metal or both. Testing in virtual machine will give you
|
||||
about 90% of the coverage for bare metal and vice versa.
|
||||
|
||||
There are other options worth of consideration too, Linux kernel has many
|
||||
debugging options that are usually disabled on runtime since they incur
|
||||
significant performance penalty. Having a few more LTP test runs with different
|
||||
debug options enabled e.g. `KASAN
|
||||
<https://www.kernel.org/doc/html/latest/dev-tools/kasan.html>`_ or `KMEMLEAK
|
||||
<https://www.kernel.org/doc/html/latest/dev-tools/kmemleak.html>`_ may help
|
||||
catch bugs before they materialize in production.
|
||||
|
||||
In practice your test matrix may easily explode and you may end up with dozens
|
||||
of differently configured testruns based on different considerations. The hard
|
||||
task at hand is not to have too many since computing power is not an infinite
|
||||
resource and does not scale that easily. If you managed to read up to this
|
||||
point *"Don't Panic!"* things are almost never as bad as they may seem at first
|
||||
glance.
|
||||
|
||||
It's a good idea to start small with an environment that models your
|
||||
production. Once that works well you can try different configurations. Select
|
||||
a few interesting ones and run them for some time in order to get an idea of
|
||||
their usefulness. If you are feeling adventurous you may try to measure and
|
||||
compare actual test coverage with one of the tools such as `gcov
|
||||
<https://www.kernel.org/doc/html/latest/dev-tools/gcov.html>`_ and `lcov
|
||||
<https://github.com/linux-test-project/lcov>`_. If you do so do not fall into a
|
||||
trap of attempting to have 100% line coverage. Having 100% of lines executed
|
||||
during the test does not mean that your test coverage is 100%. Good tests
|
||||
validate much more than just how much code from the tested binary was executed.
|
||||
|
||||
You may need to sacrifice some coverage in order to match the tests runtime to
|
||||
the available computing power. When doing so `Pareto principle
|
||||
<https://en.wikipedia.org/wiki/Pareto_principle>`_ is your friend.
|
||||
|
||||
|
||||
Test scope
|
||||
----------
|
||||
|
||||
So far we were talking about a code coverage from a point of maximizing test
|
||||
coverage while keeping our test matrix as small as possible. While that is a
|
||||
noble goal it's not the universal holy grail of testing. Different use cases
|
||||
have different considerations and scope. For a testing before a final release
|
||||
such testing is very desirable, however for a continuous integration or smoke
|
||||
testing the main requirement is that feedback loops are as short as possible.
|
||||
|
||||
When a developer changes the kernel and submits the changes to be merged it's
|
||||
desirable to run some tests. Again the hard question is which tests. If we run
|
||||
all possible tests in all possible combinations it may take a day or two and
|
||||
the developer will move to a different tasks before the tests have a chance to
|
||||
finish. If you multiply that by a number of developers in the team you may end
|
||||
up in a situation where a developer will retire before tests for his patch may
|
||||
have had a chance to finish.
|
||||
|
||||
In this case careful selection of tests is even more important. Having less is
|
||||
more in this context. One of the first ideas for CI is to skip tests that run
|
||||
for more than a second or so, happily this can be easily done with `kirk
|
||||
<https://github.com/linux-test-project/kirk/>`_. In the future we may want to
|
||||
explore some heuristics that would map the code changes in kernel into a subset
|
||||
of tests, which would allow for a very quick feedback.
|
||||
|
||||
|
||||
Debugging test failures
|
||||
-----------------------
|
||||
|
||||
You may think that you will enjoy some rest once you have your test matrix
|
||||
ready and your tests are running. Unfortunately that's where the actual work
|
||||
starts. Debugging test failures is probably the hardest part of the testing
|
||||
process. In some cases failures are easily reproducible and it's not that hard
|
||||
to locate the bug, either in the test or in the kernel itself. There are
|
||||
however, quite common, cases where the test failure reproduces only in 10% or
|
||||
even 1% of the test runs. Sometimes tests are not failing in isolation, that is
|
||||
because operating system has a huge internal state and a test failure manifests
|
||||
only after running right sequence of tests. All of that does not mean that
|
||||
there is no bug, that usually means that the bug depends on more prerequisites
|
||||
that have to manifest at the right time in order to trigger the failure. Sadly
|
||||
for modern systems that are asynchronous in nature such bugs are more and more
|
||||
common.
|
||||
|
||||
The debugging process itself is not complicated by its nature. You have to
|
||||
attempt to understand the failure by checking the logs, reading and
|
||||
understanding the source code, debugging with strace, gdb, etc. Then form a
|
||||
hypothesis and either prove or disprove it. Rinse and repeat until you end up
|
||||
with a clear description of what went wrong. Hopefully you will manage to find
|
||||
the root cause, but you should not be discouraged, if you do not. Debugging
|
||||
kernel bugs takes a lot of experience and skill one can say as much as is
|
||||
needed to write the kernel code.
|
||||
|
||||
|
||||
Happy testing!
|
||||
@@ -1,5 +0,0 @@
|
||||
/*.txt
|
||||
/docbook-xsl.css
|
||||
/metadata.html
|
||||
/metadata.pdf
|
||||
/metadata.chunked/
|
||||
@@ -1,69 +0,0 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
# Copyright (c) 2019 Cyril Hrubis <chrubis@suse.cz>
|
||||
# Copyright (c) 2020 Petr Vorel <pvorel@suse.cz>
|
||||
|
||||
top_srcdir ?= ..
|
||||
|
||||
include $(top_srcdir)/include/mk/env_pre.mk
|
||||
include $(top_srcdir)/include/mk/functions.mk
|
||||
|
||||
ifeq ($(METADATA_GENERATOR),asciidoctor)
|
||||
METADATA_GENERATOR_CMD := asciidoctor
|
||||
METADATA_GENERATOR_PARAMS := -d book metadata.txt
|
||||
METADATA_GENERATOR_PARAMS_HTML := -b xhtml
|
||||
METADATA_GENERATOR_PARAMS_PDF := -b pdf -r asciidoctor-pdf
|
||||
else ifeq ($(METADATA_GENERATOR),asciidoc)
|
||||
METADATA_GENERATOR_CMD := a2x
|
||||
METADATA_GENERATOR_PARAMS := --xsltproc-opts "--stringparam toc.section.depth 1" -d book -L --resource="$(PWD)" metadata.txt
|
||||
METADATA_GENERATOR_PARAMS_HTML := -f xhtml
|
||||
METADATA_GENERATOR_PARAMS_PDF := -f pdf
|
||||
METADATA_GENERATOR_PARAMS_HTML_CHUNKED := -f chunked
|
||||
else ifeq ($(METADATA_GENERATOR),)
|
||||
$(error 'METADATA_GENERATOR' not configured, run ./configure in the root directory)
|
||||
else
|
||||
$(error '$(METADATA_GENERATOR)' not supported, only asciidoctor and asciidoc are supported)
|
||||
endif
|
||||
|
||||
ifdef VERBOSE
|
||||
METADATA_GENERATOR_PARAMS += -v
|
||||
endif
|
||||
|
||||
CLEAN_TARGETS := *.css *.js *.txt
|
||||
|
||||
ifeq ($(WITH_METADATA_HTML),yes)
|
||||
MAKE_TARGETS += metadata.html
|
||||
ifneq ($(METADATA_GENERATOR_PARAMS_HTML_CHUNKED),)
|
||||
MAKE_TARGETS += metadata.chunked
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(WITH_METADATA_PDF),yes)
|
||||
MAKE_TARGETS += metadata.pdf
|
||||
endif
|
||||
|
||||
INSTALL_DIR = metadata
|
||||
INSTALL_TARGETS = *.css *.js
|
||||
|
||||
ifndef METADATA_GENERATOR
|
||||
METADATA_GENERATOR := asciidoctor
|
||||
endif
|
||||
|
||||
txt: ${abs_top_builddir}/metadata/ltp.json
|
||||
$(abs_srcdir)/testinfo.pl $<
|
||||
|
||||
ifeq ($(WITH_METADATA_HTML),yes)
|
||||
metadata.html: txt
|
||||
$(METADATA_GENERATOR_CMD) $(METADATA_GENERATOR_PARAMS) $(METADATA_GENERATOR_PARAMS_HTML)
|
||||
|
||||
ifneq ($(METADATA_GENERATOR_PARAMS_HTML_CHUNKED),)
|
||||
metadata.chunked: txt
|
||||
$(METADATA_GENERATOR_CMD) $(METADATA_GENERATOR_PARAMS) $(METADATA_GENERATOR_PARAMS_HTML_CHUNKED)
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(WITH_METADATA_PDF),yes)
|
||||
metadata.pdf: txt
|
||||
$(METADATA_GENERATOR_CMD) $(METADATA_GENERATOR_PARAMS) $(METADATA_GENERATOR_PARAMS_PDF)
|
||||
endif
|
||||
|
||||
include $(top_srcdir)/include/mk/generic_leaf_target.mk
|
||||
@@ -1,522 +0,0 @@
|
||||
#!/usr/bin/perl
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
# Copyright (c) 2019 Cyril Hrubis <chrubis@suse.cz>
|
||||
# Copyright (c) 2020-2021 Petr Vorel <pvorel@suse.cz>
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use JSON qw(decode_json);
|
||||
use Cwd qw(abs_path);
|
||||
use File::Basename qw(dirname);
|
||||
|
||||
use constant OUTDIR => dirname(abs_path($0));
|
||||
|
||||
# tags which expect git tree, also need constant for URL
|
||||
our @TAGS_GIT = ("linux-git", "linux-stable-git", "glibc-git", "musl-git");
|
||||
|
||||
# tags should map these in lib/tst_test.c
|
||||
use constant LINUX_GIT_URL => "https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=";
|
||||
use constant LINUX_STABLE_GIT_URL => "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=";
|
||||
use constant GLIBC_GIT_URL => "https://sourceware.org/git/?p=glibc.git;a=commit;h=";
|
||||
use constant MUSL_GIT_URL => "https://git.musl-libc.org/cgit/musl/commit/src/linux/clone.c?id=";
|
||||
use constant CVE_DB_URL => "https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-";
|
||||
|
||||
sub load_json
|
||||
{
|
||||
my ($fname, $mode) = @_;
|
||||
local $/;
|
||||
|
||||
open(my $fh, '<', $fname) or die("Can't open $fname $!");
|
||||
|
||||
return <$fh>;
|
||||
}
|
||||
|
||||
sub log_info
|
||||
{
|
||||
my $msg = shift;
|
||||
print STDERR "INFO: $msg\n";
|
||||
}
|
||||
|
||||
sub log_warn
|
||||
{
|
||||
my $msg = shift;
|
||||
print STDERR "WARN: $msg\n";
|
||||
}
|
||||
|
||||
sub print_asciidoc_page
|
||||
{
|
||||
my ($fh, $json, $title, $content) = @_;
|
||||
|
||||
print $fh <<EOL;
|
||||
// -*- mode:doc; -*-
|
||||
// vim: set syntax=asciidoc:
|
||||
|
||||
$title
|
||||
|
||||
$content
|
||||
EOL
|
||||
}
|
||||
|
||||
sub tag_url {
|
||||
my ($tag, $value, $scm_url_base) = @_;
|
||||
|
||||
if ($tag eq "fname") {
|
||||
return $scm_url_base . $value;
|
||||
}
|
||||
|
||||
if ($tag eq "CVE") {
|
||||
return CVE_DB_URL . $value;
|
||||
}
|
||||
|
||||
# *_GIT_URL
|
||||
my $key = tag2env($tag) . "_URL";
|
||||
if (defined($constant::declared{"main::$key"})) {
|
||||
return eval("main::$key") . $value;
|
||||
}
|
||||
|
||||
if ('known-fail') {
|
||||
return '';
|
||||
}
|
||||
|
||||
die("unknown constant '$key' for tag $tag, define it!");
|
||||
}
|
||||
|
||||
sub bold
|
||||
{
|
||||
return "*$_[0]*";
|
||||
}
|
||||
|
||||
sub code
|
||||
{
|
||||
return "+$_[0]+";
|
||||
}
|
||||
|
||||
sub hr
|
||||
{
|
||||
return "\n\n'''\n\n";
|
||||
}
|
||||
|
||||
sub html_a
|
||||
{
|
||||
my ($url, $text) = @_;
|
||||
|
||||
# escape: ] |
|
||||
$text =~ s/([]|])/\\$1/g;
|
||||
|
||||
return "$url\[$text\]";
|
||||
}
|
||||
|
||||
sub h1
|
||||
{
|
||||
return "== $_[0]\n";
|
||||
}
|
||||
|
||||
sub h2
|
||||
{
|
||||
return "=== $_[0]\n";
|
||||
}
|
||||
|
||||
sub h3
|
||||
{
|
||||
return "==== $_[0]\n";
|
||||
}
|
||||
|
||||
sub label
|
||||
{
|
||||
return "[[$_[0]]]\n";
|
||||
}
|
||||
|
||||
sub paragraph
|
||||
{
|
||||
return "$_[0]\n\n";
|
||||
}
|
||||
|
||||
sub reference
|
||||
{
|
||||
my ($link, %args) = @_;
|
||||
|
||||
$args{text} //= $link;
|
||||
$args{delimiter} //= "";
|
||||
|
||||
return "xref:$link\[$args{text}\]$args{delimiter}\n";
|
||||
}
|
||||
|
||||
sub table
|
||||
{
|
||||
return "|===\n";
|
||||
}
|
||||
|
||||
sub table_escape
|
||||
{
|
||||
my $out = $_[0];
|
||||
|
||||
$out =~ s/\|/\\|/g;
|
||||
return $out;
|
||||
}
|
||||
|
||||
sub print_defined
|
||||
{
|
||||
my ($key, $val, $val2) = @_;
|
||||
|
||||
if (defined($val)) {
|
||||
return paragraph(bold($key) . ": " . $val . (defined($val2) ? " $val2" : ""));
|
||||
}
|
||||
}
|
||||
|
||||
sub content_about
|
||||
{
|
||||
my $json = shift;
|
||||
my $content;
|
||||
|
||||
$content .= print_defined("URL", $json->{'testsuite'}->{'url'});
|
||||
$content .= print_defined("Version", $json->{'testsuite'}->{'version'});
|
||||
$content .= print_defined("Default timeout", $json->{'defaults'}->{'timeout'}, "seconds");
|
||||
|
||||
return $content;
|
||||
}
|
||||
|
||||
sub uniq {
|
||||
my %seen;
|
||||
grep !$seen{$_}++, @_;
|
||||
}
|
||||
|
||||
sub get_test_names
|
||||
{
|
||||
my @names = @{$_[0]};
|
||||
my ($letter, $prev_letter);
|
||||
my $content;
|
||||
|
||||
for my $name (sort @names) {
|
||||
$letter = substr($name, 0, 1);
|
||||
if (defined($prev_letter) && $letter ne $prev_letter) {
|
||||
$content .= "\n";
|
||||
}
|
||||
|
||||
$content .= reference($name, delimiter => " ");
|
||||
$prev_letter = $letter;
|
||||
}
|
||||
$content .= "\n";
|
||||
|
||||
return $content;
|
||||
}
|
||||
|
||||
sub get_test_letters
|
||||
{
|
||||
my @names = @{$_[0]};
|
||||
my $letter;
|
||||
my $prev_letter = "";
|
||||
my $content;
|
||||
|
||||
for (@names) {
|
||||
$_ = substr($_, 0, 1);
|
||||
}
|
||||
@names = uniq(@names);
|
||||
|
||||
for my $letter (@names) {
|
||||
$content .= reference($letter);
|
||||
}
|
||||
$content .= "\n";
|
||||
|
||||
return $content;
|
||||
}
|
||||
|
||||
sub tag2title
|
||||
{
|
||||
my $tag = shift;
|
||||
return code(".$tag");
|
||||
}
|
||||
|
||||
sub get_filters
|
||||
{
|
||||
my $json = shift;
|
||||
my %data;
|
||||
|
||||
while (my ($k, $v) = each %{$json->{'tests'}}) {
|
||||
for my $j (keys %{$v}) {
|
||||
next if ($j eq 'fname' || $j eq 'doc');
|
||||
$data{$j} = () unless (defined($data{$j}));
|
||||
|
||||
if ($j eq 'tags') {
|
||||
for my $tags (@{$v}{'tags'}) {
|
||||
for my $tag (@$tags) {
|
||||
my $k2 = $$tag[0];
|
||||
my $v2 = $$tag[1];
|
||||
$data{$j}{$k2} = () unless (defined($data{$j}{$k2}));
|
||||
push @{$data{$j}{$k2}}, $k unless grep{$_ eq $k} @{$data{$j}{$k2}};
|
||||
}
|
||||
}
|
||||
} else {
|
||||
push @{$data{$j}}, $k unless grep{$_ eq $k} @{$data{$j}};
|
||||
}
|
||||
}
|
||||
}
|
||||
return \%data;
|
||||
}
|
||||
|
||||
sub content_filter
|
||||
{
|
||||
my $k = $_[0];
|
||||
my $title = $_[1];
|
||||
my $desc = $_[2];
|
||||
my $h = $_[3];
|
||||
my ($letter, $prev_letter, $content);
|
||||
|
||||
$content = label($k);
|
||||
$content .= $title;
|
||||
$content .= paragraph("Tests containing $desc flag.");
|
||||
|
||||
$content .= get_test_names(\@{$h});
|
||||
|
||||
return $content;
|
||||
}
|
||||
|
||||
sub content_filters
|
||||
{
|
||||
my $json = shift;
|
||||
my $data = get_filters($json);
|
||||
my %h = %$data;
|
||||
my $content;
|
||||
|
||||
for my $k (sort keys %$data) {
|
||||
my $title = tag2title($k);
|
||||
if (ref($h{$k}) eq 'HASH') {
|
||||
$content .= label($k);
|
||||
$content .= h2($title);
|
||||
for my $k2 (sort keys %{$h{$k}}) {
|
||||
my $title2 = code($k2);
|
||||
$content .= content_filter($k2, h3($title2), "$title $title2", $h{$k}{$k2});
|
||||
}
|
||||
} else {
|
||||
$content .= content_filter($k, h2($title), $title, \@{$h{$k}});
|
||||
}
|
||||
}
|
||||
|
||||
return $content;
|
||||
}
|
||||
|
||||
sub tag2env
|
||||
{
|
||||
my $tag = shift;
|
||||
$tag =~ s/-/_/g;
|
||||
return uc($tag);
|
||||
}
|
||||
|
||||
sub detect_git
|
||||
{
|
||||
my %data;
|
||||
|
||||
for my $tag (@TAGS_GIT) {
|
||||
my $env = tag2env($tag);
|
||||
|
||||
unless (defined $ENV{$env} && $ENV{$env}) {
|
||||
log_warn("git repository $tag not defined. Define it in \$$env");
|
||||
next;
|
||||
}
|
||||
|
||||
unless (-d $ENV{$env}) {
|
||||
log_warn("\$$env does not exit ('$ENV{$env}')");
|
||||
next;
|
||||
}
|
||||
|
||||
if (system("which git >/dev/null")) {
|
||||
log_warn("git not in \$PATH ('$ENV{'PATH'}')");
|
||||
next;
|
||||
}
|
||||
|
||||
chdir($ENV{$env});
|
||||
if (!system("git log -1 > /dev/null")) {
|
||||
log_info("using '$ENV{$env}' as $env repository");
|
||||
$data{$tag} = $ENV{$env};
|
||||
} else {
|
||||
log_warn("git failed, git not installed or \$$env is not a git repository? ('$ENV{$env}')");
|
||||
}
|
||||
chdir(OUTDIR);
|
||||
}
|
||||
|
||||
return \%data;
|
||||
}
|
||||
|
||||
sub content_all_tests
|
||||
{
|
||||
my $json = shift;
|
||||
my @names = sort keys %{$json->{'tests'}};
|
||||
my $letters = paragraph(get_test_letters(\@names));
|
||||
my $git_url = detect_git();
|
||||
my $tmp = undef;
|
||||
my $printed = "";
|
||||
my $content;
|
||||
|
||||
$content .= paragraph("Total $#names tests.");
|
||||
$content .= $letters;
|
||||
$content .= get_test_names(\@names);
|
||||
|
||||
for my $name (@names) {
|
||||
my $letter = substr($name, 0, 1);
|
||||
|
||||
if ($printed ne $letter) {
|
||||
$content .= label($letter);
|
||||
$content .= h2($letter);
|
||||
$printed = $letter;
|
||||
}
|
||||
|
||||
$content .= hr() if (defined($tmp));
|
||||
$content .= label($name);
|
||||
$content .= h3($name);
|
||||
$content .= $letters;
|
||||
|
||||
if (defined($json->{'testsuite'}->{'scm_url_base'}) &&
|
||||
defined($json->{'tests'}{$name}{fname})) {
|
||||
$content .= paragraph(html_a(tag_url("fname", $json->{'tests'}{$name}{fname},
|
||||
$json->{'testsuite'}->{'scm_url_base'}), "source"));
|
||||
}
|
||||
|
||||
if (defined $json->{'tests'}{$name}{doc}) {
|
||||
for my $doc (@{$json->{'tests'}{$name}{doc}}) {
|
||||
|
||||
# fix formatting for asciidoc [DOCUMENTATION] => *Documentation*
|
||||
if ($doc =~ s/^\[(.*)\]$/$1/) {
|
||||
$doc = paragraph(bold(ucfirst(lc($doc))));
|
||||
}
|
||||
|
||||
$content .= "$doc\n";
|
||||
}
|
||||
$content .= "\n";
|
||||
}
|
||||
|
||||
if ($json->{'tests'}{$name}{timeout}) {
|
||||
if ($json->{'tests'}{$name}{timeout} eq -1) {
|
||||
$content .= paragraph("Test timeout is disabled");
|
||||
} else {
|
||||
$content .= paragraph("Test timeout is $json->{'tests'}{$name}{timeout} seconds");
|
||||
}
|
||||
} else {
|
||||
$content .= paragraph("Test timeout defaults to $json->{'defaults'}->{'timeout'} seconds");
|
||||
}
|
||||
|
||||
my $tmp2 = undef;
|
||||
for my $k (sort keys %{$json->{'tests'}{$name}}) {
|
||||
my $v = $json->{'tests'}{$name}{$k};
|
||||
next if ($k eq "tags" || $k eq "fname" || $k eq "doc");
|
||||
if (!defined($tmp2)) {
|
||||
$content .= table . "|Key|Value\n\n"
|
||||
}
|
||||
|
||||
$content .= "|" . reference($k, text => tag2title($k)) . "\n|";
|
||||
|
||||
if (ref($v) eq 'ARRAY') {
|
||||
# two dimensional array
|
||||
if (ref(@$v[0]) eq 'ARRAY') {
|
||||
for my $v2 (@$v) {
|
||||
$content .= paragraph(table_escape(join(' ', @$v2)));
|
||||
}
|
||||
} else {
|
||||
# one dimensional array
|
||||
$content .= table_escape(join(', ', @$v));
|
||||
}
|
||||
} else {
|
||||
# plain content
|
||||
$content .= table_escape($v);
|
||||
}
|
||||
|
||||
$content .= "\n";
|
||||
|
||||
$tmp2 = 1;
|
||||
}
|
||||
if (defined($tmp2)) {
|
||||
$content .= table . "\n";
|
||||
}
|
||||
|
||||
$tmp2 = undef;
|
||||
my %commits;
|
||||
my @sorted_tags = sort { $a->[0] cmp $b->[0] } @{$json->{'tests'}{$name}{tags} // []};
|
||||
|
||||
for my $tag (@sorted_tags) {
|
||||
if (!defined($tmp2)) {
|
||||
$content .= table . "|Tag|Info\n"
|
||||
}
|
||||
my $k = @$tag[0];
|
||||
my $v = @$tag[1];
|
||||
my $url;
|
||||
|
||||
if (defined($$git_url{$k})) {
|
||||
$commits{$k} = () unless (defined($commits{$k}));
|
||||
unless (defined($commits{$k}{$v})) {
|
||||
chdir($$git_url{$k});
|
||||
$commits{$k}{$v} = `git log --pretty=format:'%s' -1 $v`;
|
||||
chdir(OUTDIR);
|
||||
}
|
||||
$v .= ' ("' . $commits{$k}{$v} . '")';
|
||||
}
|
||||
|
||||
$url = tag_url($k, @$tag[1]);
|
||||
if ($url) {
|
||||
$v = html_a($url, $v);
|
||||
}
|
||||
|
||||
# tag value value can be split into more lines if too long
|
||||
# i.e. URL in known-fail
|
||||
for (@$tag[2 .. $#$tag]) {
|
||||
$v .= " $_";
|
||||
}
|
||||
|
||||
$content .= "\n|" . reference($k) . "\n|$v\n";
|
||||
$tmp2 = 1;
|
||||
}
|
||||
if (defined($tmp2)) {
|
||||
$content .= table . "\n";
|
||||
}
|
||||
|
||||
$tmp = 1;
|
||||
}
|
||||
|
||||
return $content;
|
||||
}
|
||||
|
||||
|
||||
my $json = decode_json(load_json($ARGV[0]));
|
||||
|
||||
my $config = [
|
||||
{
|
||||
file => "about.txt",
|
||||
title => h2("About $json->{'testsuite'}->{'name'}"),
|
||||
content => \&content_about,
|
||||
},
|
||||
{
|
||||
file => "filters.txt",
|
||||
title => h1("Test filtered by used flags"),
|
||||
content => \&content_filters,
|
||||
},
|
||||
{
|
||||
file => "all-tests.txt",
|
||||
title => h1("All tests"),
|
||||
content => \&content_all_tests,
|
||||
},
|
||||
];
|
||||
|
||||
sub print_asciidoc_main
|
||||
{
|
||||
my $config = shift;
|
||||
my $file = "metadata.txt";
|
||||
my $content;
|
||||
|
||||
open(my $fh, '>', $file) or die("Can't open $file $!");
|
||||
|
||||
$content = <<EOL;
|
||||
:doctype: inline
|
||||
:sectanchors:
|
||||
:toc:
|
||||
|
||||
EOL
|
||||
for my $c (@{$config}) {
|
||||
$content .= "include::$c->{'file'}\[\]\n";
|
||||
}
|
||||
print_asciidoc_page($fh, $json, h1($json->{'testsuite'}->{'short_name'} . " test catalog"), $content);
|
||||
}
|
||||
|
||||
for my $c (@{$config}) {
|
||||
open(my $fh, '>', $c->{'file'}) or die("Can't open $c->{'file'} $!");
|
||||
print_asciidoc_page($fh, $json, $c->{'title'}, $c->{'content'}->($json));
|
||||
}
|
||||
|
||||
print_asciidoc_main($config);
|
||||
+2
-2
@@ -18,8 +18,8 @@ MAKE_TARGETS :=
|
||||
distclean:: clean ac-distclean
|
||||
maintainer-clean:: distclean ac-maintainer-clean
|
||||
ac-clean ac-distclean::
|
||||
$(RM) -f config.h
|
||||
ac-maintainer-clean::
|
||||
$(RM) -f config.h lapi/syscalls.h stamp-h1
|
||||
ac-maintainer-clean:: ac-clean
|
||||
$(RM) -f config.h.in
|
||||
|
||||
vpath %.h $(abs_srcdir)
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* Copyright (c) 2024 Cyril Hrubis <chrubis@suse.cz>
|
||||
*/
|
||||
#ifndef LAPI_ARCH_PRCTL_H__
|
||||
#define LAPI_ARCH_PRCTL_H__
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifdef HAVE_ASM_PRCTL_H
|
||||
# include <asm/prctl.h>
|
||||
#endif
|
||||
|
||||
#ifndef ARCH_GET_CPUID
|
||||
# define ARCH_GET_CPUID 0x1011
|
||||
#endif
|
||||
|
||||
#ifndef ARCH_SET_CPUID
|
||||
# define ARCH_SET_CPUID 0x1012
|
||||
#endif
|
||||
|
||||
#endif /* LAPI_ARCH_PRCTL_H__ */
|
||||
@@ -0,0 +1,19 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* Copyright (c) 2025 Linux Test Project
|
||||
* Li Wang <liwang@redhat.com>
|
||||
*/
|
||||
|
||||
#ifndef LAPI_BLKDEV_H__
|
||||
#define LAPI_BLKDEV_H__
|
||||
|
||||
#ifdef HAVE_LINUX_BLKDEV_H
|
||||
#include <linux/blkdev.h>
|
||||
#endif
|
||||
|
||||
/* Define BLK_MAX_BLOCK_SIZE for older kernels */
|
||||
#ifndef BLK_MAX_BLOCK_SIZE
|
||||
#define BLK_MAX_BLOCK_SIZE 0x00010000 /* 64K */
|
||||
#endif
|
||||
|
||||
#endif /* LAPI_BLKDEV_H */
|
||||
+16
-12
@@ -10,14 +10,10 @@
|
||||
|
||||
#ifdef HAVE_SYS_CAPABILITY_H
|
||||
# include <sys/capability.h>
|
||||
/**
|
||||
* Some old libcap-devel(1.96~2.16) define _LINUX_TYPES_H in
|
||||
* sys/capability.h that makes ltp-lib cann't include linux/types.h
|
||||
* essentially. Here undefine it if include such old header-file.
|
||||
*/
|
||||
# ifndef HAVE_NEWER_LIBCAP
|
||||
# undef _LINUX_TYPES_H
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef CAP_NET_BIND_SERVICE
|
||||
# define CAP_NET_BIND_SERVICE 10
|
||||
#endif
|
||||
|
||||
#ifndef CAP_NET_RAW
|
||||
@@ -36,18 +32,26 @@
|
||||
# define CAP_SYS_ADMIN 21
|
||||
#endif
|
||||
|
||||
#ifndef CAP_SYS_NICE
|
||||
# define CAP_SYS_NICE 23
|
||||
#endif
|
||||
|
||||
#ifndef CAP_SYS_TIME
|
||||
# define CAP_SYS_TIME 25
|
||||
#endif
|
||||
|
||||
#ifndef CAP_AUDIT_READ
|
||||
# define CAP_AUDIT_READ 37
|
||||
#endif
|
||||
|
||||
#ifndef CAP_SYS_RESOURCE
|
||||
# define CAP_SYS_RESOURCE 24
|
||||
#endif
|
||||
|
||||
#ifndef CAP_MKNOD
|
||||
# define CAP_MKNOD 27
|
||||
#endif
|
||||
|
||||
#ifndef CAP_AUDIT_READ
|
||||
# define CAP_AUDIT_READ 37
|
||||
#endif
|
||||
|
||||
#ifndef CAP_BPF
|
||||
# define CAP_BPF 39
|
||||
#endif
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#ifndef LAPI_COMMON_TIMERS_H__
|
||||
#define LAPI_COMMON_TIMERS_H__
|
||||
|
||||
#include <linux/version.h>
|
||||
#include "config.h"
|
||||
#include "lapi/syscalls.h"
|
||||
#include "lapi/posix_clocks.h"
|
||||
@@ -30,6 +31,8 @@ static const clock_t clock_list[] = {
|
||||
/* MAX_CLOCKS is the maximum number of clock sources supported by kernel */
|
||||
#define MAX_CLOCKS 16
|
||||
|
||||
#define MAX_AUX_CLOCKS 8
|
||||
|
||||
#define CLOCK_TO_STR(def_name) \
|
||||
case def_name: \
|
||||
return #def_name;
|
||||
|
||||
@@ -32,6 +32,10 @@
|
||||
#define FAN_REPORT_DFID_NAME_TARGET (FAN_REPORT_DFID_NAME | \
|
||||
FAN_REPORT_FID | FAN_REPORT_TARGET_FID)
|
||||
#endif
|
||||
#ifndef FAN_REPORT_FD_ERROR
|
||||
#define FAN_REPORT_FD_ERROR 0x00002000
|
||||
#endif
|
||||
|
||||
|
||||
/* Non-uapi convenience macros */
|
||||
#ifndef FAN_REPORT_DFID_NAME_FID
|
||||
@@ -105,6 +109,9 @@
|
||||
#ifndef FAN_FS_ERROR
|
||||
#define FAN_FS_ERROR 0x00008000
|
||||
#endif
|
||||
#ifndef FAN_PRE_ACCESS
|
||||
#define FAN_PRE_ACCESS 0x00100000
|
||||
#endif
|
||||
#ifndef FAN_RENAME
|
||||
#define FAN_RENAME 0x10000000
|
||||
#endif
|
||||
@@ -117,6 +124,16 @@
|
||||
#define FAN_EPIDFD -2
|
||||
#endif
|
||||
|
||||
/* errno other than EPERM can specified in upper byte of deny response */
|
||||
#ifndef FAN_DENY_ERRNO
|
||||
#define FAN_ERRNO(err) (((((__u32)(err)) & 0xff) << 24))
|
||||
#define FAN_DENY_ERRNO(err) (FAN_DENY | FAN_ERRNO(err))
|
||||
#endif
|
||||
|
||||
#ifndef FAN_RESPONSE_ERRNO
|
||||
#define FAN_RESPONSE_ERRNO(res) ((int)((res) >> 24))
|
||||
#endif
|
||||
|
||||
/* Flags required for unprivileged user group */
|
||||
#define FANOTIFY_REQUIRED_USER_INIT_FLAGS (FAN_REPORT_FID)
|
||||
|
||||
@@ -130,6 +147,8 @@
|
||||
#define LTP_ALL_PERM_EVENTS (FAN_OPEN_PERM | FAN_OPEN_EXEC_PERM | \
|
||||
FAN_ACCESS_PERM)
|
||||
|
||||
#define LTP_PRE_CONTENT_EVENTS (FAN_PRE_ACCESS)
|
||||
|
||||
struct fanotify_group_type {
|
||||
unsigned int flag;
|
||||
const char *name;
|
||||
@@ -162,6 +181,9 @@ typedef struct {
|
||||
#ifndef FAN_EVENT_INFO_TYPE_ERROR
|
||||
#define FAN_EVENT_INFO_TYPE_ERROR 5
|
||||
#endif
|
||||
#ifndef FAN_EVENT_INFO_TYPE_RANGE
|
||||
#define FAN_EVENT_INFO_TYPE_RANGE 6
|
||||
#endif
|
||||
|
||||
#ifndef FAN_EVENT_INFO_TYPE_OLD_DFID_NAME
|
||||
#define FAN_EVENT_INFO_TYPE_OLD_DFID_NAME 10
|
||||
@@ -201,6 +223,15 @@ struct fanotify_event_info_error {
|
||||
};
|
||||
#endif /* HAVE_STRUCT_FANOTIFY_EVENT_INFO_ERROR */
|
||||
|
||||
#ifndef HAVE_STRUCT_FANOTIFY_EVENT_INFO_RANGE
|
||||
struct fanotify_event_info_range {
|
||||
struct fanotify_event_info_header hdr;
|
||||
__u32 pad;
|
||||
__u64 offset;
|
||||
__u64 count;
|
||||
};
|
||||
#endif /* HAVE_STRUCT_FANOTIFY_EVENT_INFO_RANGE */
|
||||
|
||||
/* NOTE: only for struct fanotify_event_info_fid */
|
||||
#ifdef HAVE_STRUCT_FANOTIFY_EVENT_INFO_FID_FSID___VAL
|
||||
# define FSID_VAL_MEMBER(fsid, i) (fsid.__val[i])
|
||||
@@ -208,4 +239,9 @@ struct fanotify_event_info_error {
|
||||
# define FSID_VAL_MEMBER(fsid, i) (fsid.val[i])
|
||||
#endif /* HAVE_STRUCT_FANOTIFY_EVENT_INFO_FID_FSID___VAL */
|
||||
|
||||
/* linux/exportfs.h */
|
||||
#ifndef FILEID_INVALID
|
||||
# define FILEID_INVALID 0xff
|
||||
#endif
|
||||
|
||||
#endif /* LAPI_FANOTIFY_H__ */
|
||||
|
||||
@@ -94,6 +94,10 @@
|
||||
# define AT_REMOVEDIR 0x200
|
||||
#endif
|
||||
|
||||
#ifndef AT_HANDLE_FID
|
||||
# define AT_HANDLE_FID AT_REMOVEDIR
|
||||
#endif
|
||||
|
||||
#ifndef AT_SYMLINK_FOLLOW
|
||||
# define AT_SYMLINK_FOLLOW 0x400
|
||||
#endif
|
||||
@@ -150,6 +154,14 @@
|
||||
# define RENAME_WHITEOUT (1 << 2)
|
||||
#endif
|
||||
|
||||
#ifndef F_LINUX_SPECIFIC_BASE
|
||||
#define F_LINUX_SPECIFIC_BASE 1024
|
||||
#endif
|
||||
|
||||
#ifndef F_CREATED_QUERY
|
||||
#define F_CREATED_QUERY (F_LINUX_SPECIFIC_BASE + 4)
|
||||
#endif
|
||||
|
||||
/* splice, vmsplice, tee */
|
||||
|
||||
#ifndef SPLICE_F_NONBLOCK
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* Copyright (C) 2024 Andrea Cervesato <andrea.cervesato@suse.com>
|
||||
* Copyright (C) 2024 Cyril Hrubis <chrubis@suse.cz>
|
||||
*/
|
||||
|
||||
#ifndef LAPI_FICLONE_H__
|
||||
#define LAPI_FICLONE_H__
|
||||
|
||||
#include "config.h"
|
||||
#include <linux/fs.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifndef HAVE_STRUCT_FILE_CLONE_RANGE
|
||||
struct file_clone_range {
|
||||
int64_t src_fd;
|
||||
uint64_t src_offset;
|
||||
uint64_t src_length;
|
||||
uint64_t dest_offset;
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifndef FICLONE
|
||||
# define FICLONE _IOW(0x94, 9, int)
|
||||
#endif
|
||||
|
||||
#ifndef FICLONERANGE
|
||||
# define FICLONERANGE _IOW(0x94, 13, struct file_clone_range)
|
||||
#endif
|
||||
|
||||
#endif /* LAPI_FICLONE_H__ */
|
||||
+73
-7
@@ -10,15 +10,28 @@
|
||||
#define LAPI_FS_H__
|
||||
|
||||
#include "config.h"
|
||||
#ifndef HAVE_MOUNT_SETATTR
|
||||
# ifdef HAVE_LINUX_FS_H
|
||||
# include <linux/fs.h>
|
||||
# endif
|
||||
#ifndef HAVE_LINUX_FS
|
||||
# include <linux/fs.h>
|
||||
#endif
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/user.h>
|
||||
#include <limits.h>
|
||||
#include "tst_test.h"
|
||||
#include "lapi/abisize.h"
|
||||
#include "lapi/syscalls.h"
|
||||
|
||||
#ifndef HAVE_STRUCT_FSXATTR
|
||||
struct fsxattr {
|
||||
uint32_t fsx_xflags; /* xflags field value (get/set) */
|
||||
uint32_t fsx_extsize; /* extsize field value (get/set)*/
|
||||
uint32_t fsx_nextents; /* nextents field value (get) */
|
||||
uint32_t fsx_projid; /* project identifier (get/set) */
|
||||
uint32_t fsx_cowextsize; /* CoW extsize field value (get/set)*/
|
||||
unsigned char fsx_pad[8];
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifndef FS_IOC_GETFLAGS
|
||||
# define FS_IOC_GETFLAGS _IOR('f', 1, long)
|
||||
@@ -28,6 +41,14 @@
|
||||
# define FS_IOC_SETFLAGS _IOW('f', 2, long)
|
||||
#endif
|
||||
|
||||
#ifndef FS_IOC_FSGETXATTR
|
||||
# define FS_IOC_FSGETXATTR _IOR('X', 31, struct fsxattr)
|
||||
#endif
|
||||
|
||||
#ifndef FS_IOC_FSSETXATTR
|
||||
# define FS_IOC_FSSETXATTR _IOW('X', 32, struct fsxattr)
|
||||
#endif
|
||||
|
||||
#ifndef FS_COMPR_FL
|
||||
# define FS_COMPR_FL 0x00000004 /* Compress file */
|
||||
#endif
|
||||
@@ -48,6 +69,18 @@
|
||||
# define FS_VERITY_FL 0x00100000 /* Verity protected inode */
|
||||
#endif
|
||||
|
||||
#ifndef FS_XFLAG_APPEND
|
||||
# define FS_XFLAG_APPEND 0x00000010 /* all writes append */
|
||||
#endif
|
||||
|
||||
#ifndef FS_XFLAG_EXTSIZE
|
||||
# define FS_XFLAG_EXTSIZE 0x00000800 /* extent size allocator hint */
|
||||
#endif
|
||||
|
||||
#ifndef FS_XFLAG_COWEXTSIZE
|
||||
# define FS_XFLAG_COWEXTSIZE 0x00010000 /* CoW extent size allocator hint */
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Helper function to get MAX_LFS_FILESIZE.
|
||||
* Missing PAGE_SHIFT on some libc prevents defining MAX_LFS_FILESIZE.
|
||||
@@ -55,13 +88,13 @@
|
||||
* 64 bit: macro taken from kernel from include/linux/fs.h
|
||||
* 32 bit: own implementation
|
||||
*/
|
||||
static inline loff_t tst_max_lfs_filesize(void)
|
||||
static inline long long tst_max_lfs_filesize(void)
|
||||
{
|
||||
#ifdef TST_ABI64
|
||||
return (loff_t)LLONG_MAX;
|
||||
return LLONG_MAX;
|
||||
#else
|
||||
long page_size = getpagesize();
|
||||
loff_t ret = ULONG_MAX;
|
||||
long long ret = ULONG_MAX;
|
||||
|
||||
while (page_size >>= 1)
|
||||
ret <<= 1;
|
||||
@@ -70,4 +103,37 @@ static inline loff_t tst_max_lfs_filesize(void)
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef HAVE_STRUCT_FILE_ATTR
|
||||
struct file_attr {
|
||||
uint64_t fa_xflags; /* xflags field value (get/set) */
|
||||
uint32_t fa_extsize; /* extsize field value (get/set)*/
|
||||
uint32_t fa_nextents; /* nextents field value (get) */
|
||||
uint32_t fa_projid; /* project identifier (get/set) */
|
||||
uint32_t fa_cowextsize; /* CoW extsize field value (get/set) */
|
||||
};
|
||||
#endif
|
||||
|
||||
#define FILE_ATTR_SIZE_VER0 24
|
||||
#define FILE_ATTR_SIZE_LATEST FILE_ATTR_SIZE_VER0
|
||||
|
||||
#ifndef HAVE_FILE_GETATTR
|
||||
static inline int file_getattr(int dfd, const char *filename,
|
||||
struct file_attr *ufattr, size_t usize,
|
||||
unsigned int at_flags)
|
||||
{
|
||||
return tst_syscall(__NR_file_getattr, dfd, filename, ufattr, usize,
|
||||
at_flags);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_FILE_SETATTR
|
||||
static inline int file_setattr(int dfd, const char *filename,
|
||||
struct file_attr *ufattr, size_t usize,
|
||||
unsigned int at_flags)
|
||||
{
|
||||
return tst_syscall(__NR_file_setattr, dfd, filename, ufattr, usize,
|
||||
at_flags);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* LAPI_FS_H__ */
|
||||
|
||||
@@ -11,12 +11,11 @@
|
||||
#include "config.h"
|
||||
#include <sys/syscall.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/mount.h>
|
||||
|
||||
#ifndef HAVE_FSOPEN
|
||||
# ifdef HAVE_LINUX_MOUNT_H
|
||||
# include <linux/mount.h>
|
||||
# endif
|
||||
#if !defined(HAVE_FSOPEN) && defined(HAVE_LINUX_MOUNT_H)
|
||||
# include <linux/mount.h>
|
||||
#else
|
||||
# include <sys/mount.h>
|
||||
#endif
|
||||
|
||||
#include "lapi/fcntl.h"
|
||||
@@ -119,6 +118,10 @@ static inline int mount_setattr(int dirfd, const char *from_pathname, unsigned i
|
||||
* New headers added in kernel after 5.2 release, create them for old userspace.
|
||||
*/
|
||||
|
||||
#ifndef MOVE_MOUNT_BENEATH
|
||||
# define MOVE_MOUNT_BENEATH 0x00000200
|
||||
#endif
|
||||
|
||||
#ifndef OPEN_TREE_CLONE
|
||||
|
||||
/*
|
||||
@@ -136,7 +139,7 @@ static inline int mount_setattr(int dirfd, const char *from_pathname, unsigned i
|
||||
#define MOVE_MOUNT_T_SYMLINKS 0x00000010 /* Follow symlinks on to path */
|
||||
#define MOVE_MOUNT_T_AUTOMOUNTS 0x00000020 /* Follow automounts on to path */
|
||||
#define MOVE_MOUNT_T_EMPTY_PATH 0x00000040 /* Empty to path permitted */
|
||||
#define MOVE_MOUNT__MASK 0x00000077
|
||||
#define MOVE_MOUNT__MASK 0x00000377
|
||||
|
||||
/*
|
||||
* fsopen() flags.
|
||||
|
||||
@@ -8,10 +8,14 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#if HAVE_LINUX_RANDOM_H
|
||||
#include <linux/random.h>
|
||||
#ifdef HAVE_SYS_RANDOM_H
|
||||
# include <sys/random.h>
|
||||
#else
|
||||
# include <linux/random.h>
|
||||
#endif
|
||||
|
||||
#include "lapi/syscalls.h"
|
||||
|
||||
/*
|
||||
* Flags for getrandom(2)
|
||||
*
|
||||
@@ -27,4 +31,11 @@
|
||||
# define GRND_RANDOM 0x0002
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_SYS_RANDOM_H
|
||||
static inline int getrandom(void *buf, size_t buflen, unsigned int flags)
|
||||
{
|
||||
return tst_syscall(SYS_getrandom, buf, buflen, flags);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* LAPI_GETRANDOM_H__ */
|
||||
|
||||
@@ -11,10 +11,9 @@
|
||||
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/uio.h>
|
||||
#include <stdlib.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
#include "lapi/syscalls.h"
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
|
||||
#include "config.h"
|
||||
#include <sys/ioctl.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/* musl not including it in <sys/ioctl.h> */
|
||||
#include <sys/ttydefaults.h>
|
||||
@@ -37,4 +38,136 @@ struct termio
|
||||
};
|
||||
#endif /* HAVE_STRUCT_TERMIO */
|
||||
|
||||
#ifndef HAVE_STRUCT_PROCMAP_QUERY
|
||||
#define PROCFS_IOCTL_MAGIC 'f'
|
||||
#define PROCMAP_QUERY _IOWR(PROCFS_IOCTL_MAGIC, 17, struct procmap_query)
|
||||
enum procmap_query_flags {
|
||||
/*
|
||||
* VMA permission flags.
|
||||
*
|
||||
* Can be used as part of procmap_query.query_flags field to look up
|
||||
* only VMAs satisfying specified subset of permissions. E.g., specifying
|
||||
* PROCMAP_QUERY_VMA_READABLE only will return both readable and read/write VMAs,
|
||||
* while having PROCMAP_QUERY_VMA_READABLE | PROCMAP_QUERY_VMA_WRITABLE will only
|
||||
* return read/write VMAs, though both executable/non-executable and
|
||||
* private/shared will be ignored.
|
||||
*
|
||||
* PROCMAP_QUERY_VMA_* flags are also returned in procmap_query.vma_flags
|
||||
* field to specify actual VMA permissions.
|
||||
*/
|
||||
PROCMAP_QUERY_VMA_READABLE = 0x01,
|
||||
PROCMAP_QUERY_VMA_WRITABLE = 0x02,
|
||||
PROCMAP_QUERY_VMA_EXECUTABLE = 0x04,
|
||||
PROCMAP_QUERY_VMA_SHARED = 0x08,
|
||||
/*
|
||||
* Query modifier flags.
|
||||
*
|
||||
* By default VMA that covers provided address is returned, or -ENOENT
|
||||
* is returned. With PROCMAP_QUERY_COVERING_OR_NEXT_VMA flag set, closest
|
||||
* VMA with vma_start > addr will be returned if no covering VMA is
|
||||
* found.
|
||||
*
|
||||
* PROCMAP_QUERY_FILE_BACKED_VMA instructs query to consider only VMAs that
|
||||
* have file backing. Can be combined with PROCMAP_QUERY_COVERING_OR_NEXT_VMA
|
||||
* to iterate all VMAs with file backing.
|
||||
*/
|
||||
PROCMAP_QUERY_COVERING_OR_NEXT_VMA = 0x10,
|
||||
PROCMAP_QUERY_FILE_BACKED_VMA = 0x20,
|
||||
};
|
||||
|
||||
struct procmap_query {
|
||||
/* Query struct size, for backwards/forward compatibility */
|
||||
uint64_t size;
|
||||
/*
|
||||
* Query flags, a combination of enum procmap_query_flags values.
|
||||
* Defines query filtering and behavior, see enum procmap_query_flags.
|
||||
*
|
||||
* Input argument, provided by user. Kernel doesn't modify it.
|
||||
*/
|
||||
uint64_t query_flags; /* in */
|
||||
/*
|
||||
* Query address. By default, VMA that covers this address will
|
||||
* be looked up. PROCMAP_QUERY_* flags above modify this default
|
||||
* behavior further.
|
||||
*
|
||||
* Input argument, provided by user. Kernel doesn't modify it.
|
||||
*/
|
||||
uint64_t query_addr; /* in */
|
||||
/* VMA starting (inclusive) and ending (exclusive) address, if VMA is found. */
|
||||
uint64_t vma_start; /* out */
|
||||
uint64_t vma_end; /* out */
|
||||
/* VMA permissions flags. A combination of PROCMAP_QUERY_VMA_* flags. */
|
||||
uint64_t vma_flags; /* out */
|
||||
/* VMA backing page size granularity. */
|
||||
uint64_t vma_page_size; /* out */
|
||||
/*
|
||||
* VMA file offset. If VMA has file backing, this specifies offset
|
||||
* within the file that VMA's start address corresponds to.
|
||||
* Is set to zero if VMA has no backing file.
|
||||
*/
|
||||
uint64_t vma_offset; /* out */
|
||||
/* Backing file's inode number, or zero, if VMA has no backing file. */
|
||||
uint64_t inode; /* out */
|
||||
/* Backing file's device major/minor number, or zero, if VMA has no backing file. */
|
||||
uint32_t dev_major; /* out */
|
||||
uint32_t dev_minor; /* out */
|
||||
/*
|
||||
* If set to non-zero value, signals the request to return VMA name
|
||||
* (i.e., VMA's backing file's absolute path, with " (deleted)" suffix
|
||||
* appended, if file was unlinked from FS) for matched VMA. VMA name
|
||||
* can also be some special name (e.g., "[heap]", "[stack]") or could
|
||||
* be even user-supplied with prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME).
|
||||
*
|
||||
* Kernel will set this field to zero, if VMA has no associated name.
|
||||
* Otherwise kernel will return actual amount of bytes filled in
|
||||
* user-supplied buffer (see vma_name_addr field below), including the
|
||||
* terminating zero.
|
||||
*
|
||||
* If VMA name is longer that user-supplied maximum buffer size,
|
||||
* -E2BIG error is returned.
|
||||
*
|
||||
* If this field is set to non-zero value, vma_name_addr should point
|
||||
* to valid user space memory buffer of at least vma_name_size bytes.
|
||||
* If set to zero, vma_name_addr should be set to zero as well
|
||||
*/
|
||||
uint32_t vma_name_size; /* in/out */
|
||||
/*
|
||||
* If set to non-zero value, signals the request to extract and return
|
||||
* VMA's backing file's build ID, if the backing file is an ELF file
|
||||
* and it contains embedded build ID.
|
||||
*
|
||||
* Kernel will set this field to zero, if VMA has no backing file,
|
||||
* backing file is not an ELF file, or ELF file has no build ID
|
||||
* embedded.
|
||||
*
|
||||
* Build ID is a binary value (not a string). Kernel will set
|
||||
* build_id_size field to exact number of bytes used for build ID.
|
||||
* If build ID is requested and present, but needs more bytes than
|
||||
* user-supplied maximum buffer size (see build_id_addr field below),
|
||||
* -E2BIG error will be returned.
|
||||
*
|
||||
* If this field is set to non-zero value, build_id_addr should point
|
||||
* to valid user space memory buffer of at least build_id_size bytes.
|
||||
* If set to zero, build_id_addr should be set to zero as well
|
||||
*/
|
||||
uint32_t build_id_size; /* in/out */
|
||||
/*
|
||||
* User-supplied address of a buffer of at least vma_name_size bytes
|
||||
* for kernel to fill with matched VMA's name (see vma_name_size field
|
||||
* description above for details).
|
||||
*
|
||||
* Should be set to zero if VMA name should not be returned.
|
||||
*/
|
||||
uint64_t vma_name_addr; /* in */
|
||||
/*
|
||||
* User-supplied address of a buffer of at least build_id_size bytes
|
||||
* for kernel to fill with matched VMA's ELF build ID, if available
|
||||
* (see build_id_size field description above for details).
|
||||
*
|
||||
* Should be set to zero if build ID should not be returned.
|
||||
*/
|
||||
uint64_t build_id_addr; /* in */
|
||||
};
|
||||
#endif /* HAVE_STRUCT_PROCMAP_QUERY */
|
||||
|
||||
#endif /* LAPI_IOCTL_H__ */
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#ifndef LAPI_IOCTL_NS_H__
|
||||
#define LAPI_IOCTL_NS_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <asm-generic/ioctl.h>
|
||||
|
||||
#ifndef NSIO
|
||||
@@ -23,6 +24,8 @@
|
||||
#ifndef NS_GET_NSTYPE
|
||||
#define NS_GET_NSTYPE _IO(NSIO, 0x3)
|
||||
#endif
|
||||
|
||||
#ifndef NS_GET_MNTNS_ID
|
||||
#define NS_GET_MNTNS_ID _IOR(NSIO, 0x5, uint64_t)
|
||||
#endif
|
||||
|
||||
#endif /* LAPI_IOCTL_NS_H__ */
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user