🕵️ Intro
The Linux Test Project is a joint project started years ago by SGI, OSDL and Bull developed and now maintained by IBM, Cisco, Fujitsu, SUSE, Red Hat, Oracle and many others. The project goal is to deliver tests to the open source community that validate the reliability, robustness, and stability of Linux.
In these days I’m having a journey on the project so with this article I want to show step by step how to setup the project, how tests are actually written and give you a quick and dirty guide to write your first one.
🧰 Let’s start
NOTE: Since some tests manipulate operating system settings, if you plan to run the entire testsuite it is advisable to keep your workstation clean and setup a separate environment, like a spare pc or a development virtual machine.
First thing is to install development tools and clone the repository:
# zypper in -t pattern devel_basis
or
# zypper install gcc git make pkg-config autoconf automake bison flex m4 linux-glibc-devel glibc-devel
$ git clone https://github.com/linux-test-project/ltp.git && cd ltp
$ make autotools
$ ./configure
[...omitted output...]
Now you can continue either with compiling and running a single test or with compiling and installing the whole testsuite. Lets’ do one baby step:
⚗️ One sample test
If you want to just execute a single test you actually do not need to compile the whole LTP project, so we pick up an example test for the open()
syscall . To find this specific test,
$ cd testcases/kernel/syscalls/open
$ cat open03.c
What’s inside ⁉️
|
|
This test is pretty simple, as actual code is less than 10 lines. A brief line-by-line overview:
- 1-12: standard comments, license and doc header. This project has more than 20 years of history!
- 13: include the mandatory LTP library header
- 15: a sample filename we’ll try to create calling the
open()
syscall - 17-19: the real test function: using the macros provided by the framework, send to the kernel an
open()
syscall and ensure the operation succeeds ; if by any means the syscall should return an error, the error gets automatically reported and the test result marked as failed. In any case, the value returned is stored in the variableTST_RET
- 20-22:
SAFE_*
macros let us to close and delete the file just opened in a clean way - 24-27: definition for the test metadata: which options does it need to run and which is the function that the framework will execute for us. LTP framework will look for this structure and use the informations inside. If you are curious about all the available options, you can find a good description here, but since it’s a big topic, it deserves a future dedicated post
The Linux Test Project, like the Linux Kernel itself, makes heavy use of C macros, in order to keep the tests clean, mainteinable and readable. Of course all the macros and library functions are documented and explained in the project documentation.
For a reference of the syscalls, just consult your system’s man pages. As a tip, it’s recommended to clone the upstream man repository because sometimes the man pages packaged by distributions can be sometimes lacking behind.
👟 How to run the test
Thanks to the build system setup, we can just make
our single testcase and run the standalone executable. LTP will add lots of useful information to our little program:
$ make open03
[... compiler messages omitted...]
$ ./open03
tst_test.c:1741: TINFO: LTP version: 20240129
tst_test.c:1625: TINFO: Timeout per run is 0h 00m 30s
open03.c:19: TPASS: open(TEST_FILE, O_RDWR | O_CREAT, 0700) returned fd 3
Summary:
passed 1
failed 0
broken 0
skipped 0
warnings 0
The compiled executable is also accepting some options, again courtesy of the LTP framework:
$ ./open03 -h
Environment Variables
---------------------
KCONFIG_PATH Specify kernel config file
KCONFIG_SKIP_CHECK Skip kernel config check if variable set (not set by default)
LTPROOT Prefix for installed LTP (default: /opt/ltp)
LTP_COLORIZE_OUTPUT Force colorized output behaviour (y/1 always, n/0: never)
LTP_DEV Path to the block device to be used (for .needs_device)
LTP_DEV_FS_TYPE Filesystem used for testing (default: ext2)
LTP_SINGLE_FS_TYPE Testing only - specifies filesystem instead all supported (for .all_filesystems)
LTP_TIMEOUT_MUL Timeout multiplier (must be a number >=1)
LTP_RUNTIME_MUL Runtime multiplier (must be a number >=1)
LTP_VIRT_OVERRIDE Overrides virtual machine detection (values: ""|kvm|microsoft|xen|zvm)
TMPDIR Base directory for template directory (for .needs_tmpdir, default: /tmp)
Timeout and runtime
-------------------
Test timeout (not including runtime) 0h 0m 30s
Options
-------
-h Prints this help
-i n Execute test n times
-I x Execute test for n seconds
-D Prints debug information
-V Prints LTP version
-C ARG Run child process with ARG arguments (used internally)
you can also check your source code against project best practices:
$ make check-open03
You will receive hints and errors about code quality, formatting and possible deviations from the projects’ coding standards.
🗿 Hello, new test
So if you want to write a new LTP test, you can just choose a testcases/kernel/
subfolder and create a new .c
file using a template like this:
|
|
In this example it’s important to notice that the functions setup()
and cleanup()
are meant to create/dispose test resources (like buffers, files, sockets, child processes and so on) and they get executed only once, while the run()
is the real test code and can be repeated many times.
After saving your source code with a name like mynewtest01.c
, you just need to run
$ make mynewtest01
CC testcases/kernel/syscalls/open/mynewtest01
$ ls -l mynewtest*
-rwxr-xr-x 1 andrea andrea 738064 Feb 10 11:46 mynewtest01
-rw-r--r-- 1 andrea andrea 475 Feb 10 11:46 mynewtest01.c
$ ./mynewtest01
tst_test.c:1741: TINFO: LTP version: 20240129
tst_test.c:1625: TINFO: Timeout per run is 0h 00m 30s
mynewtest01.c:5: TINFO: example setup
mynewtest01.c:15: TPASS: Doing hardly anything is easy
mynewtest01.c:10: TINFO: example cleanup
Summary:
passed 1
failed 0
broken 0
skipped 0
warnings 0
It doesn’t do anything yet but seems working, now you need only to actually implement your test logic.
Once finished and debugged, if you want the new test executed as part of the testsuite, you need to add it in one of the runtest
subfolders, where each text file defines a group of tests AKA test suite.
✅ Conclusion
If you are interested in the project, check out the project’s Wiki for other documentation and Writing Guidelines; you can also subscribe to the LTP Mailing List. Enjoy!