Name Date Size #Lines LOC

..--

android_libpthread/H25-Apr-2025-94

android_librt/H25-Apr-2025-94

newlib_tests/H25-Apr-2025-4,4412,891

tests/H25-Apr-2025-968446

.gitignoreH A D25-Apr-202539 43

MakefileH A D25-Apr-2025879 4224

README.mdH A D25-Apr-20257.5 KiB153121

cloner.cH A D25-Apr-20253.7 KiB12762

errnos.hH A D25-Apr-20253.8 KiB187154

gen_version.shH A D25-Apr-2025320 1711

get_path.cH A D25-Apr-20252.7 KiB10448

ltp.pc.inH A D25-Apr-2025192 119

parse_opts.cH A D25-Apr-202515.6 KiB603403

random_range.cH A D25-Apr-202521.6 KiB893504

safe_file_ops.cH A D25-Apr-20259.5 KiB454345

safe_macros.cH A D25-Apr-202530.3 KiB1,3581,062

safe_net.cH A D25-Apr-202513.3 KiB553428

safe_pthread.cH A D25-Apr-20255.1 KiB270199

safe_stdio.cH A D25-Apr-20252.5 KiB10267

signame.hH A D25-Apr-20252.1 KiB10778

tlibio.cH A D25-Apr-202560.4 KiB2,1721,492

tst_af_alg.cH A D25-Apr-20255.8 KiB253201

tst_ansi_color.cH A D25-Apr-20251,015 6852

tst_arch.cH A D25-Apr-20251.8 KiB9579

tst_assert.cH A D25-Apr-20252.2 KiB8458

tst_bool_expr.cH A D25-Apr-20258.1 KiB407293

tst_buffers.cH A D25-Apr-20252.9 KiB169127

tst_capability.cH A D25-Apr-20252 KiB9170

tst_cgroup.cH A D25-Apr-202537.8 KiB1,5121,063

tst_checkpoint.cH A D25-Apr-20254.5 KiB169102

tst_checksum.cH A D25-Apr-20253.4 KiB8274

tst_clocks.cH A D25-Apr-20253.5 KiB159128

tst_clone.cH A D25-Apr-2025850 4831

tst_cmd.cH A D25-Apr-20258.2 KiB348261

tst_coredump.cH A D25-Apr-2025731 3620

tst_cpu.cH A D25-Apr-20252.8 KiB10058

tst_crypto.cH A D25-Apr-20251.1 KiB5336

tst_device.cH A D25-Apr-202514.1 KiB676510

tst_dir_is_empty.cH A D25-Apr-20251.3 KiB5022

tst_epoll.cH A D25-Apr-20251.5 KiB8263

tst_fd.cH A D25-Apr-20257.2 KiB326263

tst_fill_file.cH A D25-Apr-20251.6 KiB10068

tst_fill_fs.cH A D25-Apr-20252.8 KiB145108

tst_fs_has_free.cH A D25-Apr-20251.2 KiB4517

tst_fs_link_count.cH A D25-Apr-20254.8 KiB183130

tst_fs_setup.cH A D25-Apr-20251.1 KiB5242

tst_fs_type.cH A D25-Apr-20251.6 KiB8166

tst_get_bad_addr.cH A D25-Apr-20251 KiB3211

tst_hugepage.cH A D25-Apr-20252.1 KiB8868

tst_ioctl.cH A D25-Apr-2025535 3118

tst_kconfig.cH A D25-Apr-202511.3 KiB634462

tst_kernel.cH A D25-Apr-20254.9 KiB217133

tst_kvercmp.cH A D25-Apr-20253.8 KiB193125

tst_memutils.cH A D25-Apr-20254 KiB187126

tst_mkfs.cH A D25-Apr-20252.9 KiB12687

tst_module.cH A D25-Apr-20253 KiB12587

tst_net.cH A D25-Apr-20255.3 KiB246179

tst_netdevice.cH A D25-Apr-202517 KiB643525

tst_netlink.cH A D25-Apr-202510.9 KiB500380

tst_parse_opts.cH A D25-Apr-20251.3 KiB3710

tst_path_has_mnt_flags.cH A D25-Apr-20252 KiB8447

tst_pid.cH A D25-Apr-20254.5 KiB174116

tst_process_state.cH A D25-Apr-20251.6 KiB9164

tst_rand_data.cH A D25-Apr-202516.7 KiB212208

tst_res.cH A D25-Apr-202515 KiB613392

tst_resource.cH A D25-Apr-20253.7 KiB13887

tst_rtctime.cH A D25-Apr-20252.9 KiB12884

tst_safe_file_at.cH A D25-Apr-20254.9 KiB241182

tst_safe_io_uring.cH A D25-Apr-20253.3 KiB11288

tst_safe_macros.cH A D25-Apr-202514.7 KiB713556

tst_safe_sysv_ipc.cH A D25-Apr-20255.8 KiB283221

tst_safe_timerfd.cH A D25-Apr-20251.5 KiB7051

tst_security.cH A D25-Apr-20252.7 KiB11685

tst_sig.cH A D25-Apr-20257.1 KiB256126

tst_sig_proc.cH A D25-Apr-2025471 3220

tst_status.cH A D25-Apr-20251.2 KiB7250

tst_supported_fs_types.cH A D25-Apr-20253.8 KiB189140

tst_sys_conf.cH A D25-Apr-20253 KiB148109

tst_taint.cH A D25-Apr-20252.6 KiB142113

tst_test.cH A D25-Apr-202537.9 KiB1,7721,336

tst_test_macros.cH A D25-Apr-2025665 3723

tst_thread_state.cH A D25-Apr-2025736 3925

tst_timer.cH A D25-Apr-20251.2 KiB6042

tst_timer_test.cH A D25-Apr-202511.1 KiB486329

tst_tmpdir.cH A D25-Apr-20258.3 KiB354208

tst_uid.cH A D25-Apr-20252.6 KiB12191

tst_virt.cH A D25-Apr-20254.2 KiB204135

tst_wallclock.cH A D25-Apr-20253.1 KiB11968

README.md

1# Test library design document
2
3## High-level picture
4
5    library process
6    +----------------------------+
7    | main                       |
8    |  tst_run_tcases            |
9    |   do_setup                 |
10    |   for_each_variant         |
11    |    for_each_filesystem     |   test process
12    |     fork_testrun ------------->+--------------------------------------------+
13    |      waitpid               |   | testrun                                    |
14    |                            |   |  do_test_setup                             |
15    |                            |   |   tst_test->setup                          |
16    |                            |   |  run_tests                                 |
17    |                            |   |   tst_test->test(i) or tst_test->test_all  |
18    |                            |   |  do_test_cleanup                           |
19    |                            |   |   tst_test->cleanup                        |
20    |                            |   |  exit(0)                                   |
21    |   do_exit                  |   +--------------------------------------------+
22    |    do_cleanup              |
23    |     exit(ret)              |
24    +----------------------------+
25
26## Test lifetime overview
27
28When a test is executed the very first thing to happen is that we check for
29various test prerequisites. These are described in the tst\_test structure and
30range from simple '.needs\_root' to a more complicated kernel .config boolean
31expressions such as: "CONFIG\_X86\_INTEL\_UMIP=y | CONFIG\_X86\_UMIP=y".
32
33If all checks are passed, the process continues with setting up the test
34environment as requested in the tst\_test structure. There are many different
35setup steps that have been put into the test library again ranging from rather
36simple creation of a unique test temporary directory to a bit more complicated
37ones such as preparing, formatting, and mounting a block device.
38
39The test library also initializes shared memory used for IPC at this step.
40
41Once all the prerequisites are checked and test environment has been prepared
42we can move on executing the testcase itself. The actual test is executed in a
43forked process, however there are a few hops before we get there.
44
45First of all there are test variants, which means that the test is re-executed
46several times with a slightly different setting. This is usually used to test a
47family of similar syscalls, where we test each of these syscalls exactly the
48same, but without re-executing the test binary itself. Test variants are
49implemented as a simple global variable counter that gets increased on each
50iteration. In a case of syscall tests we switch between which syscall to call
51based on the global counter.
52
53Then there is all\_filesystems flag which is mostly the same as test variants
54but executes the test for each filesystem supported by the system. Note that we
55can get cartesian product between test variants and all filesystems as well.
56
57In a pseudo code it could be expressed as:
58
59```
60for test_variants:
61	for all_filesystems:
62		fork_testrun()
63```
64
65Before we fork the test process, the test library sets up a timeout alarm and
66a heartbeat signal handler and it also sets up an alarm(2) accordingly to
67the test timeout. When a test times out, the test library gets SIGALRM and the
68alarm handler mercilessly kills all forked children by sending SIGKILL to the
69whole process group. The heartbeat handler is used by the test process to reset
70this timer for example when the test functions run in a loop.
71
72With that done we finally fork() the test process. The test process firstly
73resets signal handlers and sets its pid to be a process group leader so that we
74can slaughter all children if needed. The test library proceeds with suspending
75itself in waitpid() syscall and waits for the child to finish at this point.
76
77The test process goes ahead and calls the test setup() function if present in
78the tst\_test structure. It's important that we execute all test callbacks
79after we have forked the process, that way we cannot crash the test library
80process. The setup can also cause the test to exit prematurely by either direct
81or indirect (SAFE\_MACROS()) call to tst\_brk().  In this case the
82fork\_testrun() function exits, but the loops for test variants or filesystems
83carries on.
84
85All that is left to be done is to actually execute the tests, what happnes now
86depends on the -i and -I command line parameters that can request that the
87run() or run\_all() callbacks are executed N times or for N seconds. Again the
88test can exit at any time by direct or indirect call to tst\_brk().
89
90Once the test is finished all that is left for the test process is the test
91cleanup(). So if a there is a cleanup() callback in the tst\_test structure
92it's executed. The cleanup() callback runs in a special context where the
93tst\_brk(TBROK, ...) calls are converted into tst\_res(TWARN, ...) calls. This
94is because we found out that carrying on with partially broken cleanup is
95usually better option than exiting it in the middle.
96
97The test cleanup() is also called by the tst\_brk() handler in order to cleanup
98before exiting the test process, hence it must be able to cope even with
99partial test setup. Usually it suffices to make sure to clean up only
100resources that already have been set up and to do that in the reverse order
101that we did in setup().
102
103Once the test process exits or leaves the run() or run\_all() function the test
104library wakes up from the waitpid() call, and checks if the test process
105exited normally.
106
107Once the testrun is finished, the test library does a cleanup() as well to clean
108up resources set up in the test library setup(), reports test results and
109finally exits the process.
110
111### Test library and fork()-ing
112
113Things are a bit more complicated when fork()-ing is involved, however the test
114results are stored in a page of a shared memory and incremented by atomic
115operations, hence the results are stored right after the test reporting
116function returns from the test library and the access is, by definition,
117race-free as well.
118
119On the other hand the test library, apart from sending a SIGKILL to the whole
120process group on timeout, does not track grandchildren.
121
122This especially means that:
123
124- The test exits once the main test process exits.
125
126- While the test results are, by the design, propagated to the test library
127  we may still miss a child that gets killed by a signal or exits unexpectedly.
128
129The test writer should, because of this, take care of reaping these
130processes properly, in most cases this could be simply done by calling
131tst\_reap\_children() to collect and dissect deceased.
132
133Also note that tst\_brk() does exit only the current process, so if a child
134process calls tst\_brk() the counters are incremented and only the process
135exits.
136
137### Test library and exec()
138
139The piece of mapped memory to store the results is not preserved over
140exec(2), hence to use the test library from a binary started by an exec() it
141has to be remapped. In this case, the process must call tst\_reinit() before
142calling any other library functions. In order to make this happen the program
143environment carries LTP\_IPC\_PATH variable with a path to the backing file on
144tmpfs. This also allows us to use the test library from shell testcases.
145
146### Test library and process synchronization
147
148The piece of mapped memory is also used as a base for a futex-based
149synchronization primitives called checkpoints. And as said previously the
150memory can be mapped to any process by calling the tst\_reinit() function. As a
151matter of a fact, there is even a tst\_checkpoint binary that allows us to use
152the checkpoints from shell code as well.
153