1f08c3bdfSopenharmony_ciLTP C Test API
2f08c3bdfSopenharmony_ci==============
3f08c3bdfSopenharmony_ci
4f08c3bdfSopenharmony_ciNOTE: See also
5f08c3bdfSopenharmony_ci      https://github.com/linux-test-project/ltp/wiki/Test-Writing-Guidelines[Test Writing Guidelines],
6f08c3bdfSopenharmony_ci      https://github.com/linux-test-project/ltp/wiki/C-Test-Case-Tutorial[C Test Case Tutorial],
7f08c3bdfSopenharmony_ci      https://github.com/linux-test-project/ltp/wiki/Shell-Test-API[Shell Test API].
8f08c3bdfSopenharmony_ci
9f08c3bdfSopenharmony_ci1 Writing a test in C
10f08c3bdfSopenharmony_ci---------------------
11f08c3bdfSopenharmony_ci
12f08c3bdfSopenharmony_ci1.1 Basic test structure
13f08c3bdfSopenharmony_ci~~~~~~~~~~~~~~~~~~~~~~~~
14f08c3bdfSopenharmony_ci
15f08c3bdfSopenharmony_ciLet's start with an example, following code is a simple test for a 'getenv()'.
16f08c3bdfSopenharmony_ci
17f08c3bdfSopenharmony_ci[source,c]
18f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
19f08c3bdfSopenharmony_ci/*\
20f08c3bdfSopenharmony_ci * [Description]
21f08c3bdfSopenharmony_ci * Tests basic functionality of getenv().
22f08c3bdfSopenharmony_ci *
23f08c3bdfSopenharmony_ci *  - create an env variable and verify that getenv() can get it
24f08c3bdfSopenharmony_ci *  - call getenv() with nonexisting variable name, check that it returns NULL
25f08c3bdfSopenharmony_ci */
26f08c3bdfSopenharmony_ci
27f08c3bdfSopenharmony_ci#include "tst_test.h"
28f08c3bdfSopenharmony_ci
29f08c3bdfSopenharmony_ci#define ENV1 "LTP_TEST_ENV"
30f08c3bdfSopenharmony_ci#define ENV2 "LTP_TEST_THIS_DOES_NOT_EXIST"
31f08c3bdfSopenharmony_ci#define ENV_VAL "val"
32f08c3bdfSopenharmony_ci
33f08c3bdfSopenharmony_cistatic void setup(void)
34f08c3bdfSopenharmony_ci{
35f08c3bdfSopenharmony_ci	if (setenv(ENV1, ENV_VAL, 1))
36f08c3bdfSopenharmony_ci		tst_brk(TBROK | TERRNO, "setenv() failed");
37f08c3bdfSopenharmony_ci}
38f08c3bdfSopenharmony_ci
39f08c3bdfSopenharmony_cistatic void run(void)
40f08c3bdfSopenharmony_ci{
41f08c3bdfSopenharmony_ci	char *ret;
42f08c3bdfSopenharmony_ci
43f08c3bdfSopenharmony_ci	ret = getenv(ENV1);
44f08c3bdfSopenharmony_ci
45f08c3bdfSopenharmony_ci	if (!ret) {
46f08c3bdfSopenharmony_ci		tst_res(TFAIL, "getenv(" ENV1 ") = NULL");
47f08c3bdfSopenharmony_ci		goto next;
48f08c3bdfSopenharmony_ci	}
49f08c3bdfSopenharmony_ci
50f08c3bdfSopenharmony_ci	if (!strcmp(ret, ENV_VAL)) {
51f08c3bdfSopenharmony_ci		tst_res(TPASS, "getenv(" ENV1 ") = '"ENV_VAL "'");
52f08c3bdfSopenharmony_ci	} else {
53f08c3bdfSopenharmony_ci		tst_res(TFAIL, "getenv(" ENV1 ") = '%s', expected '"
54f08c3bdfSopenharmony_ci		               ENV_VAL "'", ret);
55f08c3bdfSopenharmony_ci	}
56f08c3bdfSopenharmony_ci
57f08c3bdfSopenharmony_cinext:
58f08c3bdfSopenharmony_ci	ret = getenv(ENV2);
59f08c3bdfSopenharmony_ci
60f08c3bdfSopenharmony_ci	if (ret)
61f08c3bdfSopenharmony_ci		tst_res(TFAIL, "getenv(" ENV2 ") = '%s'", ret);
62f08c3bdfSopenharmony_ci	else
63f08c3bdfSopenharmony_ci		tst_res(TPASS, "getenv(" ENV2 ") = NULL");
64f08c3bdfSopenharmony_ci}
65f08c3bdfSopenharmony_ci
66f08c3bdfSopenharmony_cistatic struct tst_test test = {
67f08c3bdfSopenharmony_ci	.test_all = run,
68f08c3bdfSopenharmony_ci	.setup = setup,
69f08c3bdfSopenharmony_ci};
70f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
71f08c3bdfSopenharmony_ci
72f08c3bdfSopenharmony_ciEach test includes the 'tst_test.h' header and must define the 'struct
73f08c3bdfSopenharmony_citst_test test' structure.
74f08c3bdfSopenharmony_ci
75f08c3bdfSopenharmony_ciThe overall test initialization is done in the 'setup()' function.
76f08c3bdfSopenharmony_ci
77f08c3bdfSopenharmony_ciThe overall cleanup is done in a 'cleanup()' function. Here 'cleanup()' is
78f08c3bdfSopenharmony_ciomitted as the test does not have anything to clean up. If cleanup is set in
79f08c3bdfSopenharmony_cithe test structure it's called on test exit just before the test library
80f08c3bdfSopenharmony_cicleanup. That especially means that cleanup can be called at any point in a
81f08c3bdfSopenharmony_citest execution. For example even when a test setup step has failed, therefore
82f08c3bdfSopenharmony_cithe 'cleanup()' function must be able to cope with unfinished initialization,
83f08c3bdfSopenharmony_ciand so on.
84f08c3bdfSopenharmony_ci
85f08c3bdfSopenharmony_ciThe test itself is done in the 'test()' function. The test function must work
86f08c3bdfSopenharmony_cifine if called in a loop.
87f08c3bdfSopenharmony_ci
88f08c3bdfSopenharmony_ciThere are two types of a test function pointers in the test structure. The
89f08c3bdfSopenharmony_cifirst one is a '.test_all' pointer that is used when test is implemented as a
90f08c3bdfSopenharmony_cisingle function. Then there is a '.test' function along with the number of
91f08c3bdfSopenharmony_citests '.tcnt' that allows for more detailed result reporting. If the '.test'
92f08c3bdfSopenharmony_cipointer is set the function is called '.tcnt' times with an integer parameter
93f08c3bdfSopenharmony_ciin range of [0, '.tcnt' - 1].
94f08c3bdfSopenharmony_ci
95f08c3bdfSopenharmony_ciIMPORTANT: Only one of '.test' and '.test_all' can be set at a time.
96f08c3bdfSopenharmony_ci
97f08c3bdfSopenharmony_ciEach test has a limit on how long it can run and the limit composes of two
98f08c3bdfSopenharmony_ciparts max_runtime and timeout. The max_runtime is a limit for how long can the
99f08c3bdfSopenharmony_ci'.test_all' or a set of '.test' functions take and the timeout is static part
100f08c3bdfSopenharmony_cithat should cover the duration of test setup and cleanup plus some safety.
101f08c3bdfSopenharmony_ci
102f08c3bdfSopenharmony_ciAny test that runs for more than a second or two has to make sure to:
103f08c3bdfSopenharmony_ci
104f08c3bdfSopenharmony_ci- set the runtime either by setting the '.max_runtime' in tst_test or by
105f08c3bdfSopenharmony_ci  calling 'tst_set_max_runtime()' in the test setup
106f08c3bdfSopenharmony_ci
107f08c3bdfSopenharmony_ci- monitor remaning runtime by regular calls to 'tst_remaining_runtime()' and
108f08c3bdfSopenharmony_ci  exit when runtime has been used up
109f08c3bdfSopenharmony_ci
110f08c3bdfSopenharmony_ciTest is free to exit before max_runtime has been used up for example when
111f08c3bdfSopenharmony_ciminimal number of iteration was finished.
112f08c3bdfSopenharmony_ci
113f08c3bdfSopenharmony_ciThe limit is applied to a single call of the '.test_all' function that means
114f08c3bdfSopenharmony_cithat for example when '.test_variants' or '.all_filesystems' is set the whole
115f08c3bdfSopenharmony_citest will be limited by 'variants * (max_runtime + timeout)' seconds and the
116f08c3bdfSopenharmony_citest runtime will be likely close to 'variants * max_runtime' seconds.
117f08c3bdfSopenharmony_ci
118f08c3bdfSopenharmony_ci[source,c]
119f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
120f08c3bdfSopenharmony_ci/*
121f08c3bdfSopenharmony_ci * Returns number of seconds or zero in case that runtime has been used up.
122f08c3bdfSopenharmony_ci */
123f08c3bdfSopenharmony_ci
124f08c3bdfSopenharmony_ciint tst_remaining_runtime(void);
125f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
126f08c3bdfSopenharmony_ci
127f08c3bdfSopenharmony_ciLAPI headers
128f08c3bdfSopenharmony_ci++++++++++++
129f08c3bdfSopenharmony_ci
130f08c3bdfSopenharmony_ciUse our LAPI headers ('include "lapi/foo.h"') to keep compatibility with old
131f08c3bdfSopenharmony_cidistributions. LAPI header should always include original header. Older linux
132f08c3bdfSopenharmony_ciheaders were problematic, therefore we preferred to use libc headers. There are
133f08c3bdfSopenharmony_cistill some bugs when combining certain glibc headers with linux headers, see
134f08c3bdfSopenharmony_cihttps://sourceware.org/glibc/wiki/Synchronizing_Headers.
135f08c3bdfSopenharmony_ci
136f08c3bdfSopenharmony_ciA word about the cleanup() callback
137f08c3bdfSopenharmony_ci+++++++++++++++++++++++++++++++++++
138f08c3bdfSopenharmony_ci
139f08c3bdfSopenharmony_ciThere are a few rules that needs to be followed in order to write correct
140f08c3bdfSopenharmony_cicleanup() callback.
141f08c3bdfSopenharmony_ci
142f08c3bdfSopenharmony_ci1. Free only resources that were initialized. Keep in mind that callback can
143f08c3bdfSopenharmony_ci   be executed at any point in the test run.
144f08c3bdfSopenharmony_ci
145f08c3bdfSopenharmony_ci2. Make sure to free resources in the reverse order they were
146f08c3bdfSopenharmony_ci   initialized. (Some of the steps may not depend on others and everything
147f08c3bdfSopenharmony_ci   will work if there were swapped but let's keep it in order.)
148f08c3bdfSopenharmony_ci
149f08c3bdfSopenharmony_ciThe first rule may seem complicated at first however, on the contrary, it's
150f08c3bdfSopenharmony_ciquite easy. All you have to do is to keep track of what was already
151f08c3bdfSopenharmony_ciinitialized. For example file descriptors needs to be closed only if they were
152f08c3bdfSopenharmony_ciassigned a valid file descriptor. For most of the things you need to create
153f08c3bdfSopenharmony_ciextra flag that is set right after successful initialization though. Consider,
154f08c3bdfSopenharmony_cifor example, test setup below.
155f08c3bdfSopenharmony_ci
156f08c3bdfSopenharmony_ciWe also prefer cleaning up resources that would otherwise be released on the
157f08c3bdfSopenharmony_ciprogram exit. There are two main reasons for this decision. Resources such as
158f08c3bdfSopenharmony_cifile descriptors and mmaped memory could block umounting a block device in
159f08c3bdfSopenharmony_cicases where the test library has mounted a filesystem for the test temporary
160f08c3bdfSopenharmony_cidirectory. Not freeing allocated memory would upset static analysis and tools
161f08c3bdfSopenharmony_cisuch as valgrind and produce false-positives when checking for leaks in the
162f08c3bdfSopenharmony_cilibc and other low level libraries.
163f08c3bdfSopenharmony_ci
164f08c3bdfSopenharmony_ci[source,c]
165f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
166f08c3bdfSopenharmony_cistatic int fd0, fd1, mount_flag;
167f08c3bdfSopenharmony_ci
168f08c3bdfSopenharmony_ci#define MNTPOINT "mntpoint"
169f08c3bdfSopenharmony_ci#define FILE1 "mntpoint/file1"
170f08c3bdfSopenharmony_ci#define FILE2 "mntpoint/file2"
171f08c3bdfSopenharmony_ci
172f08c3bdfSopenharmony_cistatic void setup(void)
173f08c3bdfSopenharmony_ci{
174f08c3bdfSopenharmony_ci	SAFE_MKDIR(MNTPOINT, 0777);
175f08c3bdfSopenharmony_ci	SAFE_MKFS(tst_device->dev, tst_device->fs_type, NULL, NULL);
176f08c3bdfSopenharmony_ci	SAFE_MOUNT(tst_device->dev, MNTPOINT, tst_device->fs_type, 0, 0);
177f08c3bdfSopenharmony_ci	mount_flag = 1;
178f08c3bdfSopenharmony_ci
179f08c3bdfSopenharmony_ci	fd0 = SAFE_OPEN(cleanup, FILE1, O_CREAT | O_RDWR, 0666);
180f08c3bdfSopenharmony_ci	fd1 = SAFE_OPEN(cleanup, FILE2, O_CREAT | O_RDWR, 0666);
181f08c3bdfSopenharmony_ci}
182f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
183f08c3bdfSopenharmony_ci
184f08c3bdfSopenharmony_ciIn this case the 'cleanup()' function may be invoked when any of the 'SAFE_*'
185f08c3bdfSopenharmony_cimacros has failed and therefore must be able to work with unfinished
186f08c3bdfSopenharmony_ciinitialization as well. Since global variables are initialized to zero we can
187f08c3bdfSopenharmony_cijust check that fd > 0 before we attempt to close it. The mount function
188f08c3bdfSopenharmony_cirequires extra flag to be set after device was successfully mounted.
189f08c3bdfSopenharmony_ci
190f08c3bdfSopenharmony_ci[source,c]
191f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
192f08c3bdfSopenharmony_cistatic void cleanup(void)
193f08c3bdfSopenharmony_ci{
194f08c3bdfSopenharmony_ci	if (fd1 > 0)
195f08c3bdfSopenharmony_ci		SAFE_CLOSE(fd1);
196f08c3bdfSopenharmony_ci
197f08c3bdfSopenharmony_ci	if (fd0 > 0)
198f08c3bdfSopenharmony_ci		SAFE_CLOSE(fd0);
199f08c3bdfSopenharmony_ci
200f08c3bdfSopenharmony_ci	if (mount_flag && tst_umouont(MNTPOINT))
201f08c3bdfSopenharmony_ci		tst_res(TWARN | TERRNO, "umount(%s)", MNTPOINT);
202f08c3bdfSopenharmony_ci}
203f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
204f08c3bdfSopenharmony_ci
205f08c3bdfSopenharmony_ciIMPORTANT: 'SAFE_MACROS()' used in cleanup *do not* exit the test. Failure
206f08c3bdfSopenharmony_ci           only produces a warning and the 'cleanup()' carries on. This is
207f08c3bdfSopenharmony_ci	   intentional as we want to execute as much 'cleanup()' as possible.
208f08c3bdfSopenharmony_ci
209f08c3bdfSopenharmony_ciWARNING: Calling tst_brk() in test 'cleanup()' does not exit the test as well
210f08c3bdfSopenharmony_ci         and 'TBROK' is converted to 'TWARN'.
211f08c3bdfSopenharmony_ci
212f08c3bdfSopenharmony_ciNOTE: Creation and removal of the test temporary directory is handled in
213f08c3bdfSopenharmony_ci      the test library and the directory is removed recursively. Therefore
214f08c3bdfSopenharmony_ci      we do not have to remove files and directories in the test cleanup.
215f08c3bdfSopenharmony_ci
216f08c3bdfSopenharmony_ci1.2 Basic test interface
217f08c3bdfSopenharmony_ci~~~~~~~~~~~~~~~~~~~~~~~~
218f08c3bdfSopenharmony_ci
219f08c3bdfSopenharmony_ci[source,c]
220f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
221f08c3bdfSopenharmony_civoid tst_res(int ttype, char *arg_fmt, ...);
222f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
223f08c3bdfSopenharmony_ci
224f08c3bdfSopenharmony_ciPrintf-like function to report test result, it's mostly used with ttype:
225f08c3bdfSopenharmony_ci
226f08c3bdfSopenharmony_ci|==============================
227f08c3bdfSopenharmony_ci| 'TPASS' | Test has passed.
228f08c3bdfSopenharmony_ci| 'TFAIL' | Test has failed.
229f08c3bdfSopenharmony_ci| 'TINFO' | General message.
230f08c3bdfSopenharmony_ci| 'TWARN' | Something went wrong but we decided to continue. Mostly used in cleanup functions.
231f08c3bdfSopenharmony_ci|==============================
232f08c3bdfSopenharmony_ci
233f08c3bdfSopenharmony_ciThe 'ttype' can be combined bitwise with 'TERRNO' or 'TTERRNO' to print
234f08c3bdfSopenharmony_ci'errno', 'TST_ERR' respectively.
235f08c3bdfSopenharmony_ci
236f08c3bdfSopenharmony_ci[source,c]
237f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
238f08c3bdfSopenharmony_civoid tst_brk(int ttype, char *arg_fmt, ...);
239f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
240f08c3bdfSopenharmony_ci
241f08c3bdfSopenharmony_ciPrintf-like function to report error and exit the test, it can be used with ttype:
242f08c3bdfSopenharmony_ci
243f08c3bdfSopenharmony_ci|============================================================
244f08c3bdfSopenharmony_ci| 'TBROK' | Something has failed in test preparation phase.
245f08c3bdfSopenharmony_ci| 'TCONF' | Test is not appropriate for current configuration
246f08c3bdfSopenharmony_ci            (syscall not implemented, unsupported arch, ...)
247f08c3bdfSopenharmony_ci|============================================================
248f08c3bdfSopenharmony_ci
249f08c3bdfSopenharmony_ciThe 'ttype' can be combined bitwise with 'TERRNO' or 'TTERRNO' to print
250f08c3bdfSopenharmony_ci'errno', 'TST_ERR' respectively.
251f08c3bdfSopenharmony_ci
252f08c3bdfSopenharmony_ciThere are also 'TST_EXP_*()' macros that can simplify syscall unit tests to a
253f08c3bdfSopenharmony_cisingle line, use them whenever possible. These macros take a function call as
254f08c3bdfSopenharmony_cithe first parameter and a printf-like format string and parameters as well.
255f08c3bdfSopenharmony_ciThese test macros then expand to a code that runs the call, checks the return
256f08c3bdfSopenharmony_civalue and errno and reports the test result.
257f08c3bdfSopenharmony_ci
258f08c3bdfSopenharmony_ci[source,c]
259f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
260f08c3bdfSopenharmony_cistatic void run(void)
261f08c3bdfSopenharmony_ci{
262f08c3bdfSopenharmony_ci	...
263f08c3bdfSopenharmony_ci	TST_EXP_PASS(stat(fname, &statbuf), "stat(%s, ...)", fname);
264f08c3bdfSopenharmony_ci
265f08c3bdfSopenharmony_ci	if (!TST_PASS)
266f08c3bdfSopenharmony_ci		return;
267f08c3bdfSopenharmony_ci	...
268f08c3bdfSopenharmony_ci}
269f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
270f08c3bdfSopenharmony_ci
271f08c3bdfSopenharmony_ciThe 'TST_EXP_PASS()' can be used for calls that return -1 on failure and 0 on
272f08c3bdfSopenharmony_cisuccess. It will check for the return value and reports failure if the return
273f08c3bdfSopenharmony_civalue is not equal to 0. The call also sets the 'TST_PASS' variable to 1 if
274f08c3bdfSopenharmony_cithe call succeeeded.
275f08c3bdfSopenharmony_ci
276f08c3bdfSopenharmony_ciAs seen above, this and similar macros take optional variadic arguments. These
277f08c3bdfSopenharmony_cibegin with a format string and then appropriate values to be formatted.
278f08c3bdfSopenharmony_ci
279f08c3bdfSopenharmony_ci[source,c]
280f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
281f08c3bdfSopenharmony_cistatic void run(void)
282f08c3bdfSopenharmony_ci{
283f08c3bdfSopenharmony_ci	...
284f08c3bdfSopenharmony_ci	TST_EXP_FD(open(fname, O_RDONLY), "open(%s, O_RDONLY)", fname);
285f08c3bdfSopenharmony_ci
286f08c3bdfSopenharmony_ci	SAFE_CLOSE(TST_RET);
287f08c3bdfSopenharmony_ci	...
288f08c3bdfSopenharmony_ci}
289f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
290f08c3bdfSopenharmony_ci
291f08c3bdfSopenharmony_ciThe 'TST_EXP_FD()' is the same as 'TST_EXP_PASS()' the only difference is that
292f08c3bdfSopenharmony_cithe return value is expected to be a file descriptor so the call passes if
293f08c3bdfSopenharmony_cipositive integer is returned.
294f08c3bdfSopenharmony_ci
295f08c3bdfSopenharmony_ci[source,c]
296f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
297f08c3bdfSopenharmony_cistatic void run(void)
298f08c3bdfSopenharmony_ci{
299f08c3bdfSopenharmony_ci	...
300f08c3bdfSopenharmony_ci	TST_EXP_FAIL(stat(fname, &statbuf), ENOENT, "stat(%s, ...)", fname);
301f08c3bdfSopenharmony_ci	...
302f08c3bdfSopenharmony_ci}
303f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
304f08c3bdfSopenharmony_ci
305f08c3bdfSopenharmony_ciThe 'TST_EXP_FAIL()' is similar to 'TST_EXP_PASS()' but it fails the test if
306f08c3bdfSopenharmony_cithe call haven't failed with -1 and 'errno' wasn't set to the expected one
307f08c3bdfSopenharmony_cipassed as the second argument.
308f08c3bdfSopenharmony_ci
309f08c3bdfSopenharmony_ci[source,c]
310f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
311f08c3bdfSopenharmony_cistatic void run(void)
312f08c3bdfSopenharmony_ci{
313f08c3bdfSopenharmony_ci	...
314f08c3bdfSopenharmony_ci	TST_EXP_FAIL2(msgget(key, flags), EINVAL, "msgget(%i, %i)", key, flags);
315f08c3bdfSopenharmony_ci	...
316f08c3bdfSopenharmony_ci}
317f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
318f08c3bdfSopenharmony_ci
319f08c3bdfSopenharmony_ciThe 'TST_EXP_FAIL2()' is the same as 'TST_EXP_FAIL()' except the return value is
320f08c3bdfSopenharmony_ciexpected to be non-negative integer if call passes. These macros build upon the
321f08c3bdfSopenharmony_ci+TEST()+ macro and associated variables.
322f08c3bdfSopenharmony_ci
323f08c3bdfSopenharmony_ci'TST_EXP_FAIL_SILENT()' and 'TST_EXP_FAIL2_SILENT()' variants are less verbose
324f08c3bdfSopenharmony_ciand do not print TPASS messages when SCALL fails as expected.
325f08c3bdfSopenharmony_ci
326f08c3bdfSopenharmony_ci[source,c]
327f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
328f08c3bdfSopenharmony_ciTEST(socket(AF_INET, SOCK_RAW, 1));
329f08c3bdfSopenharmony_ciif (TST_RET > -1) {
330f08c3bdfSopenharmony_ci	tst_res(TFAIL, "Created raw socket");
331f08c3bdfSopenharmony_ci	SAFE_CLOSE(TST_RET);
332f08c3bdfSopenharmony_ci} else if (TST_ERR != EPERM) {
333f08c3bdfSopenharmony_ci	tst_res(TFAIL | TTERRNO,
334f08c3bdfSopenharmony_ci		"Failed to create socket for wrong reason");
335f08c3bdfSopenharmony_ci} else {
336f08c3bdfSopenharmony_ci	tst_res(TPASS | TTERRNO, "Didn't create raw socket");
337f08c3bdfSopenharmony_ci}
338f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
339f08c3bdfSopenharmony_ci
340f08c3bdfSopenharmony_ciThe +TEST+ macro sets +TST_RET+ to its argument's return value and +TST_ERR+ to
341f08c3bdfSopenharmony_ci+errno+. The +TTERNO+ flag can be used to print the error number's symbolic
342f08c3bdfSopenharmony_civalue.
343f08c3bdfSopenharmony_ci
344f08c3bdfSopenharmony_ciNo LTP library function or macro, except those in 'tst_test_macros.h', will
345f08c3bdfSopenharmony_ciwrite to these variables (rule 'LTP-002'). So their values will not be changed
346f08c3bdfSopenharmony_ciunexpectedly.
347f08c3bdfSopenharmony_ci
348f08c3bdfSopenharmony_ci[source,c]
349f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
350f08c3bdfSopenharmony_ciTST_EXP_POSITIVE(wait(&status));
351f08c3bdfSopenharmony_ci
352f08c3bdfSopenharmony_ciif (!TST_PASS)
353f08c3bdfSopenharmony_ci	return;
354f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
355f08c3bdfSopenharmony_ci
356f08c3bdfSopenharmony_ciIf the return value of 'wait' is positive or zero, this macro will print a pass
357f08c3bdfSopenharmony_ciresult and set +TST_PASS+ appropriately. If the return value is negative, then
358f08c3bdfSopenharmony_ciit will print fail.  There are many similar macros to those shown here, please
359f08c3bdfSopenharmony_cisee 'tst_test_macros.h'.
360f08c3bdfSopenharmony_ci
361f08c3bdfSopenharmony_ci[source,c]
362f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
363f08c3bdfSopenharmony_ciTST_EXP_EQ_LI(val1, val2);
364f08c3bdfSopenharmony_ciTST_EXP_EQ_UI(val1, val2);
365f08c3bdfSopenharmony_ciTST_EXP_EQ_SZ(val1, val2);
366f08c3bdfSopenharmony_ciTST_EXP_EQ_SSZ(val1, val2);
367f08c3bdfSopenharmony_ci
368f08c3bdfSopenharmony_ci/* Use as */
369f08c3bdfSopenharmony_ciTST_EXP_EQ_LI(sig_caught, SIGCHLD);
370f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
371f08c3bdfSopenharmony_ci
372f08c3bdfSopenharmony_ciSet of macros for different integer type comparsions. These macros print the
373f08c3bdfSopenharmony_civariable names as well as values in both pass and fail scenarios.
374f08c3bdfSopenharmony_ci
375f08c3bdfSopenharmony_ci[source,c]
376f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
377f08c3bdfSopenharmony_ciconst char *tst_strsig(int sig);
378f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
379f08c3bdfSopenharmony_ci
380f08c3bdfSopenharmony_ciReturn the given signal number's corresponding string.
381f08c3bdfSopenharmony_ci
382f08c3bdfSopenharmony_ci[source,c]
383f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
384f08c3bdfSopenharmony_ciconst char *tst_strerrno(int err);
385f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
386f08c3bdfSopenharmony_ci
387f08c3bdfSopenharmony_ciReturn the given errno number's corresponding string. Using this function to
388f08c3bdfSopenharmony_citranslate 'errno' values to strings is preferred. You should not use the
389f08c3bdfSopenharmony_ci'strerror()' function in the testcases.
390f08c3bdfSopenharmony_ci
391f08c3bdfSopenharmony_ci[source,c]
392f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
393f08c3bdfSopenharmony_ciconst char *tst_strstatus(int status);
394f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
395f08c3bdfSopenharmony_ci
396f08c3bdfSopenharmony_ciReturns string describing the status as returned by 'wait()'.
397f08c3bdfSopenharmony_ci
398f08c3bdfSopenharmony_ciWARNING: This function is not thread safe.
399f08c3bdfSopenharmony_ci
400f08c3bdfSopenharmony_ci[source,c]
401f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
402f08c3bdfSopenharmony_civoid tst_set_max_runtime(int max_runtime);
403f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
404f08c3bdfSopenharmony_ci
405f08c3bdfSopenharmony_ciAllows for setting max_runtime per test iteration dynamically in the test 'setup()',
406f08c3bdfSopenharmony_cithe timeout is specified in seconds. There are a few testcases whose runtime
407f08c3bdfSopenharmony_cican vary arbitrarily, these can disable timeouts by setting it to
408f08c3bdfSopenharmony_ciTST_UNLIMITED_RUNTIME.
409f08c3bdfSopenharmony_ci
410f08c3bdfSopenharmony_ci[source,c]
411f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
412f08c3bdfSopenharmony_civoid tst_flush(void);
413f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
414f08c3bdfSopenharmony_ci
415f08c3bdfSopenharmony_ciFlush output streams, handling errors appropriately.
416f08c3bdfSopenharmony_ci
417f08c3bdfSopenharmony_ciThis function is rarely needed when you have to flush the output streams
418f08c3bdfSopenharmony_cibefore calling 'fork()' or 'clone()'. Note that the 'SAFE_FORK()' and 'SAFE_CLONE()'
419f08c3bdfSopenharmony_cicalls this function automatically. See 2.4 FILE buffers and fork() for explanation
420f08c3bdfSopenharmony_ciwhy is this needed.
421f08c3bdfSopenharmony_ci
422f08c3bdfSopenharmony_ci1.3 Test temporary directory
423f08c3bdfSopenharmony_ci~~~~~~~~~~~~~~~~~~~~~~~~~~~~
424f08c3bdfSopenharmony_ci
425f08c3bdfSopenharmony_ciIf '.needs_tmpdir' is set to '1' in the 'struct tst_test' unique test
426f08c3bdfSopenharmony_citemporary is created and it's set as the test working directory. Tests *MUST
427f08c3bdfSopenharmony_ciNOT* create temporary files outside that directory. The flag is not needed to
428f08c3bdfSopenharmony_cibe set when use these flags: '.all_filesystems', '.format_device', '.mntpoint',
429f08c3bdfSopenharmony_ci'.mount_device' '.needs_checkpoints', '.needs_device', '.resource_file'
430f08c3bdfSopenharmony_ci(these flags imply creating temporary directory).
431f08c3bdfSopenharmony_ci
432f08c3bdfSopenharmony_ciIMPORTANT: Close all file descriptors (that point to files in test temporary
433f08c3bdfSopenharmony_ci           directory, even the unlinked ones) either in the 'test()' function
434f08c3bdfSopenharmony_ci	   or in the test 'cleanup()' otherwise the test may break temporary
435f08c3bdfSopenharmony_ci	   directory removal on NFS (look for "NFS silly rename").
436f08c3bdfSopenharmony_ci
437f08c3bdfSopenharmony_ci1.4 Safe macros
438f08c3bdfSopenharmony_ci~~~~~~~~~~~~~~~
439f08c3bdfSopenharmony_ci
440f08c3bdfSopenharmony_ciSafe macros aim to simplify error checking in test preparation. Instead of
441f08c3bdfSopenharmony_cicalling system API functions, checking for their return value and aborting the
442f08c3bdfSopenharmony_citest if the operation has failed, you just use corresponding safe macro.
443f08c3bdfSopenharmony_ci
444f08c3bdfSopenharmony_ciUse them whenever it's possible.
445f08c3bdfSopenharmony_ci
446f08c3bdfSopenharmony_ciInstead of writing:
447f08c3bdfSopenharmony_ci
448f08c3bdfSopenharmony_ci[source,c]
449f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
450f08c3bdfSopenharmony_cifd = open("/dev/null", O_RDONLY);
451f08c3bdfSopenharmony_ciif (fd < 0)
452f08c3bdfSopenharmony_ci	tst_brk(TBROK | TERRNO, "opening /dev/null failed");
453f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
454f08c3bdfSopenharmony_ci
455f08c3bdfSopenharmony_ciYou write just:
456f08c3bdfSopenharmony_ci
457f08c3bdfSopenharmony_ci[source,c]
458f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
459f08c3bdfSopenharmony_cifd = SAFE_OPEN("/dev/null", O_RDONLY);
460f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
461f08c3bdfSopenharmony_ci
462f08c3bdfSopenharmony_ciIMPORTANT: The 'SAFE_CLOSE()' function also sets the passed file descriptor to -1
463f08c3bdfSopenharmony_ci           after it's successfully closed.
464f08c3bdfSopenharmony_ci
465f08c3bdfSopenharmony_ciThey can also simplify reading and writing of sysfs files, you can, for
466f08c3bdfSopenharmony_ciexample, do:
467f08c3bdfSopenharmony_ci
468f08c3bdfSopenharmony_ci[source,c]
469f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
470f08c3bdfSopenharmony_ciSAFE_FILE_SCANF("/proc/sys/kernel/pid_max", "%lu", &pid_max);
471f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
472f08c3bdfSopenharmony_ci
473f08c3bdfSopenharmony_ciSee 'include/tst_safe_macros.h', 'include/tst_safe_stdio.h' and
474f08c3bdfSopenharmony_ci'include/tst_safe_file_ops.h' and 'include/tst_safe_net.h' for a complete list.
475f08c3bdfSopenharmony_ci
476f08c3bdfSopenharmony_ci1.5 Test specific command line options
477f08c3bdfSopenharmony_ci~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
478f08c3bdfSopenharmony_ci
479f08c3bdfSopenharmony_ci[source,c]
480f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
481f08c3bdfSopenharmony_cistruct tst_option {
482f08c3bdfSopenharmony_ci        char *optstr;
483f08c3bdfSopenharmony_ci        char **arg;
484f08c3bdfSopenharmony_ci        char *help;
485f08c3bdfSopenharmony_ci};
486f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
487f08c3bdfSopenharmony_ci
488f08c3bdfSopenharmony_ciTest specific command line parameters can be passed with the 'NULL' terminated
489f08c3bdfSopenharmony_ciarray of 'struct tst_option'. The 'optstr' is the command line option i.e. "o"
490f08c3bdfSopenharmony_cior "o:" if option has a parameter. Only short options are supported. The 'arg'
491f08c3bdfSopenharmony_ciis where 'optarg' is stored upon match. If option has no parameter it's set to
492f08c3bdfSopenharmony_cinon-'NULL' value if option was present. The 'help' is a short help string.
493f08c3bdfSopenharmony_ci
494f08c3bdfSopenharmony_ciNOTE: The test parameters must not collide with common test parameters defined
495f08c3bdfSopenharmony_ci      in the library the currently used ones are +-i+, +-I+, +-C+, and +-h+.
496f08c3bdfSopenharmony_ci
497f08c3bdfSopenharmony_ci[source,c]
498f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
499f08c3bdfSopenharmony_ciint tst_parse_int(const char *str, int *val, int min, int max);
500f08c3bdfSopenharmony_ciint tst_parse_long(const char *str, long *val, long min, long max);
501f08c3bdfSopenharmony_ciint tst_parse_float(const char *str, float *val, float min, float max);
502f08c3bdfSopenharmony_ciint tst_parse_filesize(const char *str, long long *val, long long min, long long max);
503f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
504f08c3bdfSopenharmony_ci
505f08c3bdfSopenharmony_ciHelpers for parsing the strings returned in the 'struct tst_option'.
506f08c3bdfSopenharmony_ci
507f08c3bdfSopenharmony_ciHelpers return zero on success and 'errno', mostly 'EINVAL' or 'ERANGE', on
508f08c3bdfSopenharmony_cifailure.
509f08c3bdfSopenharmony_ci
510f08c3bdfSopenharmony_ciHelpers functions are no-op if 'str' is 'NULL'.
511f08c3bdfSopenharmony_ci
512f08c3bdfSopenharmony_ciThe valid range for result includes both 'min' and 'max'.
513f08c3bdfSopenharmony_ci
514f08c3bdfSopenharmony_ciIn particular, 'tst_parse_filesize' function accepts prefix multiplies such as
515f08c3bdfSopenharmony_ci"k/K for kilobytes, "m/M" for megabytes and "g/G" for gigabytes. For example,
516f08c3bdfSopenharmony_ci10K are converted into 10240 bytes.
517f08c3bdfSopenharmony_ci
518f08c3bdfSopenharmony_ci[source,c]
519f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
520f08c3bdfSopenharmony_ci#include <limits.h>
521f08c3bdfSopenharmony_ci#include "tst_test.h"
522f08c3bdfSopenharmony_ci
523f08c3bdfSopenharmony_cistatic char *str_threads;
524f08c3bdfSopenharmony_cistatic int threads = 10;
525f08c3bdfSopenharmony_ci
526f08c3bdfSopenharmony_cistatic void setup(void)
527f08c3bdfSopenharmony_ci{
528f08c3bdfSopenharmony_ci	if (tst_parse_int(str_threads, &threads, 1, INT_MAX))
529f08c3bdfSopenharmony_ci		tst_brk(TBROK, "Invalid number of threads '%s'", str_threads);
530f08c3bdfSopenharmony_ci
531f08c3bdfSopenharmony_ci	...
532f08c3bdfSopenharmony_ci}
533f08c3bdfSopenharmony_ci
534f08c3bdfSopenharmony_cistatic void test_threads(void)
535f08c3bdfSopenharmony_ci{
536f08c3bdfSopenharmony_ci	...
537f08c3bdfSopenharmony_ci
538f08c3bdfSopenharmony_ci	for (i = 0; i < threads; i++) {
539f08c3bdfSopenharmony_ci		...
540f08c3bdfSopenharmony_ci	}
541f08c3bdfSopenharmony_ci
542f08c3bdfSopenharmony_ci	...
543f08c3bdfSopenharmony_ci}
544f08c3bdfSopenharmony_ci
545f08c3bdfSopenharmony_cistatic struct tst_test test = {
546f08c3bdfSopenharmony_ci	...
547f08c3bdfSopenharmony_ci	.options = (struct tst_option[]) {
548f08c3bdfSopenharmony_ci		{"t:", &str_threads, "Number of threads (default 10)"},
549f08c3bdfSopenharmony_ci		{},
550f08c3bdfSopenharmony_ci	...
551f08c3bdfSopenharmony_ci};
552f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
553f08c3bdfSopenharmony_ci
554f08c3bdfSopenharmony_ci
555f08c3bdfSopenharmony_ci1.6 Runtime kernel version detection
556f08c3bdfSopenharmony_ci~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
557f08c3bdfSopenharmony_ci
558f08c3bdfSopenharmony_ciTestcases for newly added kernel functionality require kernel newer than a
559f08c3bdfSopenharmony_cicertain version to run. All you need to skip a test on older kernels is to
560f08c3bdfSopenharmony_ciset the '.min_kver' string in the 'struct tst_test' to a minimal required
561f08c3bdfSopenharmony_cikernel version, e.g. '.min_kver = "4.10.0"'.
562f08c3bdfSopenharmony_ci
563f08c3bdfSopenharmony_ciFor more complicated operations such as skipping a test for a certain range
564f08c3bdfSopenharmony_ciof kernel versions, following functions could be used:
565f08c3bdfSopenharmony_ci
566f08c3bdfSopenharmony_ci[source,c]
567f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
568f08c3bdfSopenharmony_ciint tst_kvercmp(int r1, int r2, int r3);
569f08c3bdfSopenharmony_ci
570f08c3bdfSopenharmony_cistruct tst_kern_exv {
571f08c3bdfSopenharmony_ci        char *dist_name;
572f08c3bdfSopenharmony_ci        char *extra_ver;
573f08c3bdfSopenharmony_ci};
574f08c3bdfSopenharmony_ci
575f08c3bdfSopenharmony_ciint tst_kvercmp2(int r1, int r2, int r3, struct tst_kern_exv *vers);
576f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
577f08c3bdfSopenharmony_ci
578f08c3bdfSopenharmony_ciThese two functions are intended for runtime kernel version detection. They
579f08c3bdfSopenharmony_ciparse the output from 'uname()' and compare it to the passed values.
580f08c3bdfSopenharmony_ci
581f08c3bdfSopenharmony_ciThe return value is similar to the 'strcmp()' function, i.e. zero means equal,
582f08c3bdfSopenharmony_cinegative value means that the kernel is older than the expected value and
583f08c3bdfSopenharmony_cipositive means that it's newer.
584f08c3bdfSopenharmony_ci
585f08c3bdfSopenharmony_ciThe second function 'tst_kvercmp2()' allows for specifying per-vendor table of
586f08c3bdfSopenharmony_cikernel versions as vendors typically backport fixes to their kernels and the
587f08c3bdfSopenharmony_citest may be relevant even if the kernel version does not suggests so.
588f08c3bdfSopenharmony_ci
589f08c3bdfSopenharmony_ci[source,c]
590f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
591f08c3bdfSopenharmony_ciif (tst_kvercmp(5, 19, 0) >= 0)
592f08c3bdfSopenharmony_ci	tst_res(TCONF, "Test valid only for kernel < 5.19");
593f08c3bdfSopenharmony_ci
594f08c3bdfSopenharmony_cistatic struct tst_kern_exv kvers[] = {
595f08c3bdfSopenharmony_ci	{ "UBUNTU", "4.4.0-48.69" },
596f08c3bdfSopenharmony_ci	{ NULL, NULL},
597f08c3bdfSopenharmony_ci};
598f08c3bdfSopenharmony_ci
599f08c3bdfSopenharmony_ciif (tst_kvercmp2(4, 4, 27, kvers) < 0)
600f08c3bdfSopenharmony_ci	/* code for kernel < v4.4.27 or ubuntu kernel < 4.4.0-48.69 */
601f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
602f08c3bdfSopenharmony_ci
603f08c3bdfSopenharmony_ciWARNING: The shell 'tst_kvercmp' maps the result into unsigned integer - the
604f08c3bdfSopenharmony_ci         process exit value.
605f08c3bdfSopenharmony_ci
606f08c3bdfSopenharmony_ciNOTE: See also LTP
607f08c3bdfSopenharmony_ci      https://github.com/linux-test-project/ltp/wiki/Supported-kernel,-libc,-toolchain-versions#13-minimal-supported-kernel-version[minimal supported kernel version].
608f08c3bdfSopenharmony_ci
609f08c3bdfSopenharmony_ci1.7 Fork()-ing
610f08c3bdfSopenharmony_ci~~~~~~~~~~~~~~
611f08c3bdfSopenharmony_ci
612f08c3bdfSopenharmony_ciBe wary that if the test forks and there were messages printed by the
613f08c3bdfSopenharmony_ci'tst_*()' interfaces, the data may still be in libc/kernel buffers and these
614f08c3bdfSopenharmony_ci*ARE NOT* flushed automatically.
615f08c3bdfSopenharmony_ci
616f08c3bdfSopenharmony_ciThis happens when 'stdout' gets redirected to a file. In this case, the
617f08c3bdfSopenharmony_ci'stdout' is not line buffered, but block buffered. Hence after a fork content
618f08c3bdfSopenharmony_ciof the buffers will be printed by the parent and each of the children.
619f08c3bdfSopenharmony_ci
620f08c3bdfSopenharmony_ciTo avoid that you should use 'SAFE_FORK()', 'SAFE_CLONE()' or 'tst_clone()'.
621f08c3bdfSopenharmony_ci
622f08c3bdfSopenharmony_ciIMPORTANT: You have to set the '.forks_child' flag in the test structure
623f08c3bdfSopenharmony_ci           if your testcase forks or calls 'SAFE_CLONE()'.
624f08c3bdfSopenharmony_ci
625f08c3bdfSopenharmony_ci1.8 Doing the test in the child process
626f08c3bdfSopenharmony_ci~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
627f08c3bdfSopenharmony_ci
628f08c3bdfSopenharmony_ciResults reported by 'tst_res()' are propagated to the parent test process via
629f08c3bdfSopenharmony_ciblock of shared memory.
630f08c3bdfSopenharmony_ci
631f08c3bdfSopenharmony_ciCalling 'tst_brk()' causes child process to exit with non-zero exit value.
632f08c3bdfSopenharmony_ciWhich means that it's safe to use 'SAFE_*()' macros in the child processes as
633f08c3bdfSopenharmony_ciwell.
634f08c3bdfSopenharmony_ci
635f08c3bdfSopenharmony_ciChildren that outlive the 'test()' function execution are waited for in the
636f08c3bdfSopenharmony_citest library. Unclean child exit (killed by signal, non-zero exit value, etc.)
637f08c3bdfSopenharmony_ciwill cause the main test process to exit with 'tst_brk()', which especially
638f08c3bdfSopenharmony_cimeans that 'TBROK' propagated from a child process will cause the whole test
639f08c3bdfSopenharmony_cito exit with 'TBROK'.
640f08c3bdfSopenharmony_ci
641f08c3bdfSopenharmony_ciIf a test needs a child that segfaults or does anything else that cause it to
642f08c3bdfSopenharmony_ciexit uncleanly all you need to do is to wait for such children from the
643f08c3bdfSopenharmony_ci'test()' function so that it's reaped before the main test exits the 'test()'
644f08c3bdfSopenharmony_cifunction.
645f08c3bdfSopenharmony_ci
646f08c3bdfSopenharmony_ci[source,c]
647f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
648f08c3bdfSopenharmony_ci#include "tst_test.h"
649f08c3bdfSopenharmony_ci
650f08c3bdfSopenharmony_civoid tst_reap_children(void);
651f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
652f08c3bdfSopenharmony_ci
653f08c3bdfSopenharmony_ciThe 'tst_reap_children()' function makes the process wait for all of its
654f08c3bdfSopenharmony_cichildren and exits with 'tst_brk(TBROK, ...)' if any of them returned
655f08c3bdfSopenharmony_cia non zero exit code.
656f08c3bdfSopenharmony_ci
657f08c3bdfSopenharmony_ciWhen using 'SAFE_CLONE' or 'tst_clone', this may not work depending on
658f08c3bdfSopenharmony_cithe parameters passed to clone. The following call to 'SAFE_CLONE' is
659f08c3bdfSopenharmony_ciidentical to 'fork()', so will work as expected.
660f08c3bdfSopenharmony_ci
661f08c3bdfSopenharmony_ci[source,c]
662f08c3bdfSopenharmony_ci--------------------------------------------------------------------------------
663f08c3bdfSopenharmony_ciconst struct tst_clone_args args = {
664f08c3bdfSopenharmony_ci	.exit_signal = SIGCHLD,
665f08c3bdfSopenharmony_ci};
666f08c3bdfSopenharmony_ci
667f08c3bdfSopenharmony_ciSAFE_CLONE(&args);
668f08c3bdfSopenharmony_ci--------------------------------------------------------------------------------
669f08c3bdfSopenharmony_ci
670f08c3bdfSopenharmony_ciIf 'exit_signal' is set to something else, then this will break
671f08c3bdfSopenharmony_ci'tst_reap_children'. It's not expected that all parameters to clone will
672f08c3bdfSopenharmony_ciwork with the LTP library unless specific action is taken by the test code.
673f08c3bdfSopenharmony_ci
674f08c3bdfSopenharmony_ci.Using 'tst_res()' from binaries started by 'exec()'
675f08c3bdfSopenharmony_ci[source,c]
676f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
677f08c3bdfSopenharmony_ci/* test.c */
678f08c3bdfSopenharmony_ci#define _GNU_SOURCE
679f08c3bdfSopenharmony_ci#include <unistd.h>
680f08c3bdfSopenharmony_ci#include "tst_test.h"
681f08c3bdfSopenharmony_ci
682f08c3bdfSopenharmony_cistatic void do_test(void)
683f08c3bdfSopenharmony_ci{
684f08c3bdfSopenharmony_ci	char *const argv[] = {"test_exec_child", NULL};
685f08c3bdfSopenharmony_ci	char path[4096];
686f08c3bdfSopenharmony_ci
687f08c3bdfSopenharmony_ci	if (tst_get_path("test_exec_child", path, sizeof(path)))
688f08c3bdfSopenharmony_ci		tst_brk(TCONF, "Couldn't find test_exec_child in $PATH");
689f08c3bdfSopenharmony_ci
690f08c3bdfSopenharmony_ci	execve(path, argv, environ);
691f08c3bdfSopenharmony_ci
692f08c3bdfSopenharmony_ci	tst_res(TFAIL | TERRNO, "EXEC!");
693f08c3bdfSopenharmony_ci}
694f08c3bdfSopenharmony_ci
695f08c3bdfSopenharmony_cistatic struct tst_test test = {
696f08c3bdfSopenharmony_ci	.test_all = do_test,
697f08c3bdfSopenharmony_ci	.child_needs_reinit = 1,
698f08c3bdfSopenharmony_ci};
699f08c3bdfSopenharmony_ci
700f08c3bdfSopenharmony_ci/* test_exec_child.c */
701f08c3bdfSopenharmony_ci#define TST_NO_DEFAULT_MAIN
702f08c3bdfSopenharmony_ci#include "tst_test.h"
703f08c3bdfSopenharmony_ci
704f08c3bdfSopenharmony_ciint main(void)
705f08c3bdfSopenharmony_ci{
706f08c3bdfSopenharmony_ci	tst_reinit();
707f08c3bdfSopenharmony_ci	tst_res(TPASS, "Child passed!");
708f08c3bdfSopenharmony_ci	return 0;
709f08c3bdfSopenharmony_ci}
710f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
711f08c3bdfSopenharmony_ci
712f08c3bdfSopenharmony_ciThe 'tst_res()' function can be also used from binaries started by 'exec()',
713f08c3bdfSopenharmony_cithe parent test process has to set the '.child_needs_reinit' flag so that the
714f08c3bdfSopenharmony_cilibrary prepares for it and has to make sure the 'LTP_IPC_PATH' environment
715f08c3bdfSopenharmony_civariable is passed down, then the very first thing the program has to call in
716f08c3bdfSopenharmony_ci'main()' is 'tst_reinit()' that sets up the IPC.
717f08c3bdfSopenharmony_ci
718f08c3bdfSopenharmony_ci1.9 Fork() and Parent-child synchronization
719f08c3bdfSopenharmony_ci~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
720f08c3bdfSopenharmony_ci
721f08c3bdfSopenharmony_ciAs LTP tests are written for Linux, most of the tests involve fork()-ing and
722f08c3bdfSopenharmony_ciparent-child process synchronization. LTP includes a checkpoint library that
723f08c3bdfSopenharmony_ciprovides wait/wake futex based functions.
724f08c3bdfSopenharmony_ci
725f08c3bdfSopenharmony_ciIn order to use checkpoints the '.needs_checkpoints' flag in the 'struct
726f08c3bdfSopenharmony_citst_test' must be set to '1', this causes the test library to initialize
727f08c3bdfSopenharmony_cicheckpoints before the 'test()' function is called.
728f08c3bdfSopenharmony_ci
729f08c3bdfSopenharmony_ci[source,c]
730f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
731f08c3bdfSopenharmony_ci#include "tst_test.h"
732f08c3bdfSopenharmony_ci
733f08c3bdfSopenharmony_ciTST_CHECKPOINT_WAIT(id)
734f08c3bdfSopenharmony_ci
735f08c3bdfSopenharmony_ciTST_CHECKPOINT_WAIT2(id, msec_timeout)
736f08c3bdfSopenharmony_ci
737f08c3bdfSopenharmony_ciTST_CHECKPOINT_WAKE(id)
738f08c3bdfSopenharmony_ci
739f08c3bdfSopenharmony_ciTST_CHECKPOINT_WAKE2(id, nr_wake)
740f08c3bdfSopenharmony_ci
741f08c3bdfSopenharmony_ciTST_CHECKPOINT_WAKE_AND_WAIT(id)
742f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
743f08c3bdfSopenharmony_ci
744f08c3bdfSopenharmony_ciThe checkpoint interface provides pair of wake and wait functions. The 'id' is
745f08c3bdfSopenharmony_ciunsigned integer which specifies checkpoint to wake/wait for. As a matter of
746f08c3bdfSopenharmony_cifact it's an index to an array stored in a shared memory, so it starts on
747f08c3bdfSopenharmony_ci'0' and there should be enough room for at least of hundred of them.
748f08c3bdfSopenharmony_ci
749f08c3bdfSopenharmony_ciThe 'TST_CHECKPOINT_WAIT()' and 'TST_CHECKPOINT_WAIT2()' suspends process
750f08c3bdfSopenharmony_ciexecution until it's woken up or until timeout is reached.
751f08c3bdfSopenharmony_ci
752f08c3bdfSopenharmony_ciThe 'TST_CHECKPOINT_WAKE()' wakes one process waiting on the checkpoint.
753f08c3bdfSopenharmony_ciIf no process is waiting the function retries until it success or until
754f08c3bdfSopenharmony_citimeout is reached.
755f08c3bdfSopenharmony_ci
756f08c3bdfSopenharmony_ciIf timeout has been reached process exits with appropriate error message (uses
757f08c3bdfSopenharmony_ci'tst_brk()').
758f08c3bdfSopenharmony_ci
759f08c3bdfSopenharmony_ciThe 'TST_CHECKPOINT_WAKE2()' does the same as 'TST_CHECKPOINT_WAKE()' but can
760f08c3bdfSopenharmony_cibe used to wake precisely 'nr_wake' processes.
761f08c3bdfSopenharmony_ci
762f08c3bdfSopenharmony_ciThe 'TST_CHECKPOINT_WAKE_AND_WAIT()' is a shorthand for doing wake and then
763f08c3bdfSopenharmony_ciimmediately waiting on the same checkpoint.
764f08c3bdfSopenharmony_ci
765f08c3bdfSopenharmony_ciChild processes created via 'SAFE_FORK()' are ready to use the checkpoint
766f08c3bdfSopenharmony_cisynchronization functions, as they inherited the mapped page automatically.
767f08c3bdfSopenharmony_ci
768f08c3bdfSopenharmony_ciChild processes started via 'exec()', or any other processes not forked from
769f08c3bdfSopenharmony_cithe test process must initialize the checkpoint by calling 'tst_reinit()'.
770f08c3bdfSopenharmony_ci
771f08c3bdfSopenharmony_ciFor the details of the interface, look into the 'include/tst_checkpoint.h'.
772f08c3bdfSopenharmony_ci
773f08c3bdfSopenharmony_ci[source,c]
774f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
775f08c3bdfSopenharmony_ci#include "tst_test.h"
776f08c3bdfSopenharmony_ci
777f08c3bdfSopenharmony_ci/*
778f08c3bdfSopenharmony_ci * Waits for process state change.
779f08c3bdfSopenharmony_ci *
780f08c3bdfSopenharmony_ci * The state is one of the following:
781f08c3bdfSopenharmony_ci *
782f08c3bdfSopenharmony_ci * R - process is running
783f08c3bdfSopenharmony_ci * S - process is sleeping
784f08c3bdfSopenharmony_ci * D - process sleeping uninterruptibly
785f08c3bdfSopenharmony_ci * Z - zombie process
786f08c3bdfSopenharmony_ci * T - process is traced
787f08c3bdfSopenharmony_ci */
788f08c3bdfSopenharmony_ciTST_PROCESS_STATE_WAIT(pid, state, msec_timeout)
789f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
790f08c3bdfSopenharmony_ci
791f08c3bdfSopenharmony_ciThe 'TST_PROCESS_STATE_WAIT()' waits until process 'pid' is in requested
792f08c3bdfSopenharmony_ci'state' or timeout is reached. The call polls +/proc/pid/stat+ to get this
793f08c3bdfSopenharmony_ciinformation. A timeout of 0 will wait infinitely.
794f08c3bdfSopenharmony_ci
795f08c3bdfSopenharmony_ciOn timeout -1 is returned and errno set to ETIMEDOUT.
796f08c3bdfSopenharmony_ci
797f08c3bdfSopenharmony_ciIt's mostly used with state 'S' which means that process is sleeping in kernel
798f08c3bdfSopenharmony_cifor example in 'pause()' or any other blocking syscall.
799f08c3bdfSopenharmony_ci
800f08c3bdfSopenharmony_ci1.10 Signals and signal handlers
801f08c3bdfSopenharmony_ci~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
802f08c3bdfSopenharmony_ci
803f08c3bdfSopenharmony_ciIf you need to use signal handlers, keep the code short and simple. Don't
804f08c3bdfSopenharmony_ciforget that the signal handler is called asynchronously and can interrupt the
805f08c3bdfSopenharmony_cicode execution at any place.
806f08c3bdfSopenharmony_ci
807f08c3bdfSopenharmony_ciThis means that problems arise when global state is changed both from the test
808f08c3bdfSopenharmony_cicode and signal handler, which will occasionally lead to:
809f08c3bdfSopenharmony_ci
810f08c3bdfSopenharmony_ci* Data corruption (data gets into inconsistent state), this may happen, for
811f08c3bdfSopenharmony_ci  example, for any operations on 'FILE' objects.
812f08c3bdfSopenharmony_ci
813f08c3bdfSopenharmony_ci* Deadlock, this happens, for example, if you call 'malloc(2)', 'free(2)',
814f08c3bdfSopenharmony_ci  etc. from both the test code and the signal handler at the same time since
815f08c3bdfSopenharmony_ci  'malloc' has global lock for it's internal data structures. (Be wary that
816f08c3bdfSopenharmony_ci  'malloc(2)' is used by the libc functions internally too.)
817f08c3bdfSopenharmony_ci
818f08c3bdfSopenharmony_ci* Any other unreproducible and unexpected behavior.
819f08c3bdfSopenharmony_ci
820f08c3bdfSopenharmony_ciQuite common mistake is to call 'exit(3)' from a signal handler. Note that this
821f08c3bdfSopenharmony_cifunction is not signal-async-safe as it flushes buffers, etc. If you need to
822f08c3bdfSopenharmony_ciexit a test immediately from a signal handler use '_exit(2)' instead.
823f08c3bdfSopenharmony_ci
824f08c3bdfSopenharmony_ciTIP: See 'man 7 signal' for the list of signal-async-safe functions.
825f08c3bdfSopenharmony_ci
826f08c3bdfSopenharmony_ciIf a signal handler sets a variable, its declaration must be 'volatile',
827f08c3bdfSopenharmony_ciotherwise compiler may misoptimize the code. This is because the variable may
828f08c3bdfSopenharmony_cinot be changed in the compiler code flow analysis. There is 'sig_atomic_t'
829f08c3bdfSopenharmony_citype defined in C99 but this one *DOES NOT* imply 'volatile' (it's just a
830f08c3bdfSopenharmony_ci'typedef' to 'int'). So the correct type for a flag that is changed from a
831f08c3bdfSopenharmony_cisignal handler is either 'volatile int' or 'volatile sig_atomic_t'.
832f08c3bdfSopenharmony_ci
833f08c3bdfSopenharmony_ciIf a crash (e.g. triggered by signal SIGSEGV) is expected in testing, you
834f08c3bdfSopenharmony_cican avoid creation of core files by calling 'tst_no_corefile()' function.
835f08c3bdfSopenharmony_ciThis takes effect for process (and its children) which invoked it, unless
836f08c3bdfSopenharmony_cithey subsequently modify RLIMIT_CORE.
837f08c3bdfSopenharmony_ci
838f08c3bdfSopenharmony_ciNote that LTP library will reap any processes that test didn't reap itself,
839f08c3bdfSopenharmony_ciand report any non-zero exit code as failure.
840f08c3bdfSopenharmony_ci
841f08c3bdfSopenharmony_ci1.11 Kernel Modules
842f08c3bdfSopenharmony_ci~~~~~~~~~~~~~~~~~~~
843f08c3bdfSopenharmony_ci
844f08c3bdfSopenharmony_ciThere are certain cases where the test needs a kernel part and userspace part,
845f08c3bdfSopenharmony_cihappily, LTP can build a kernel module and then insert it to the kernel on test
846f08c3bdfSopenharmony_cistart for you. See 'testcases/kernel/device-drivers/block' for details.
847f08c3bdfSopenharmony_ci
848f08c3bdfSopenharmony_ci1.12 Useful macros
849f08c3bdfSopenharmony_ci~~~~~~~~~~~~~~~~~~
850f08c3bdfSopenharmony_ci
851f08c3bdfSopenharmony_ciThese macros are defined in 'include/tst_common.h'.
852f08c3bdfSopenharmony_ci
853f08c3bdfSopenharmony_ci[source,c]
854f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
855f08c3bdfSopenharmony_ciARRAY_SIZE(arr)
856f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
857f08c3bdfSopenharmony_ci
858f08c3bdfSopenharmony_ciReturns the size of statically defined array, i.e.
859f08c3bdfSopenharmony_ci'(sizeof(arr) / sizeof(*arr))'
860f08c3bdfSopenharmony_ci
861f08c3bdfSopenharmony_ci[source,c]
862f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
863f08c3bdfSopenharmony_ciLTP_ALIGN(x, a)
864f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
865f08c3bdfSopenharmony_ci
866f08c3bdfSopenharmony_ciAligns the x to be next multiple of a. The a must be power of 2.
867f08c3bdfSopenharmony_ci
868f08c3bdfSopenharmony_ci[source,c]
869f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
870f08c3bdfSopenharmony_ciTST_TO_STR(s)  /* stringification */
871f08c3bdfSopenharmony_ciTST_TO_STR_(s) /* macro expansion */
872f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
873f08c3bdfSopenharmony_ci
874f08c3bdfSopenharmony_ciMacros for stringification.
875f08c3bdfSopenharmony_ci
876f08c3bdfSopenharmony_ci1.13 Filesystem type detection and skiplist
877f08c3bdfSopenharmony_ci~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
878f08c3bdfSopenharmony_ci
879f08c3bdfSopenharmony_ciSome tests are known to fail on certain filesystems (you cannot swap on TMPFS,
880f08c3bdfSopenharmony_cithere are unimplemented 'fcntl()' etc.).
881f08c3bdfSopenharmony_ci
882f08c3bdfSopenharmony_ciIf your test needs to be skipped on certain filesystems use the
883f08c3bdfSopenharmony_ci'.skip_filesystems' field in the tst_test structure as follows:
884f08c3bdfSopenharmony_ci
885f08c3bdfSopenharmony_ci[source,c]
886f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
887f08c3bdfSopenharmony_ci#include "tst_test.h"
888f08c3bdfSopenharmony_ci
889f08c3bdfSopenharmony_cistatic struct tst_test test = {
890f08c3bdfSopenharmony_ci	...
891f08c3bdfSopenharmony_ci        .skip_filesystems = (const char *const []) {
892f08c3bdfSopenharmony_ci                "tmpfs",
893f08c3bdfSopenharmony_ci                "ramfs",
894f08c3bdfSopenharmony_ci                "nfs",
895f08c3bdfSopenharmony_ci                NULL
896f08c3bdfSopenharmony_ci        },
897f08c3bdfSopenharmony_ci};
898f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
899f08c3bdfSopenharmony_ci
900f08c3bdfSopenharmony_ciWhen the '.all_filesystems' flag is set the '.skip_filesystems' list is passed
901f08c3bdfSopenharmony_cito the function that detects supported filesystems any listed filesystem is
902f08c3bdfSopenharmony_cinot included in the resulting list of supported filesystems.
903f08c3bdfSopenharmony_ci
904f08c3bdfSopenharmony_ciIf test needs to adjust expectations based on filesystem type it's also
905f08c3bdfSopenharmony_cipossible to detect filesystem type at the runtime. This is preferably used
906f08c3bdfSopenharmony_ciwhen only subset of the test is not applicable for a given filesystem.
907f08c3bdfSopenharmony_ci
908f08c3bdfSopenharmony_ciNOTE: ext2, ext3 or ext4 in '.skip_filesystems' on tests which does *not* use
909f08c3bdfSopenharmony_ci      '.all_filesystems' needs to be defined as 'ext2/ext3/ext4'. The reason
910f08c3bdfSopenharmony_ci      is that it is hard to detect used filesystem due to overlapping the functionality.
911f08c3bdfSopenharmony_ci      OTOH tests which use '.skip_filesystems' *with* '.all_filesystems' can skip
912f08c3bdfSopenharmony_ci      only filesystems which are actually used in '.all_filesystems': ext2, ext3,
913f08c3bdfSopenharmony_ci      ext4, xfs, btrfs, vfat, exfat, ntfs, tmpfs (defined in 'fs_type_whitelist[]').
914f08c3bdfSopenharmony_ci      It does not make sense to list other filesystems.
915f08c3bdfSopenharmony_ci
916f08c3bdfSopenharmony_ci
917f08c3bdfSopenharmony_ci[source,c]
918f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
919f08c3bdfSopenharmony_ci#include "tst_test.h"
920f08c3bdfSopenharmony_ci
921f08c3bdfSopenharmony_cistatic void run(void)
922f08c3bdfSopenharmony_ci{
923f08c3bdfSopenharmony_ci	...
924f08c3bdfSopenharmony_ci
925f08c3bdfSopenharmony_ci	switch ((type = tst_fs_type("."))) {
926f08c3bdfSopenharmony_ci	case TST_NFS_MAGIC:
927f08c3bdfSopenharmony_ci	case TST_TMPFS_MAGIC:
928f08c3bdfSopenharmony_ci	case TST_RAMFS_MAGIC:
929f08c3bdfSopenharmony_ci		tst_brk(TCONF, "Subtest not supported on %s",
930f08c3bdfSopenharmony_ci		        tst_fs_type_name(type));
931f08c3bdfSopenharmony_ci		return;
932f08c3bdfSopenharmony_ci	break;
933f08c3bdfSopenharmony_ci	}
934f08c3bdfSopenharmony_ci
935f08c3bdfSopenharmony_ci	...
936f08c3bdfSopenharmony_ci}
937f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
938f08c3bdfSopenharmony_ci
939f08c3bdfSopenharmony_ci1.14 Thread-safety in the LTP library
940f08c3bdfSopenharmony_ci~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
941f08c3bdfSopenharmony_ci
942f08c3bdfSopenharmony_ciIt is safe to use library 'tst_res()' function in multi-threaded tests.
943f08c3bdfSopenharmony_ci
944f08c3bdfSopenharmony_ciOnly the main thread must return from the 'test()' function to the test
945f08c3bdfSopenharmony_cilibrary and that must be done only after all threads that may call any library
946f08c3bdfSopenharmony_cifunction has been terminated. That especially means that threads that may call
947f08c3bdfSopenharmony_ci'tst_brk()' must terminate before the execution of the 'test()' function
948f08c3bdfSopenharmony_cireturns to the library. This is usually done by the main thread joining all
949f08c3bdfSopenharmony_ciworker threads at the end of the 'test()' function. Note that the main thread
950f08c3bdfSopenharmony_ciwill never get to the library code in a case that 'tst_brk()' was called from
951f08c3bdfSopenharmony_cione of the threads since it will sleep at least in 'pthread_join()' on the
952f08c3bdfSopenharmony_cithread that called the 'tst_brk()' till 'exit()' is called by 'tst_brk()'.
953f08c3bdfSopenharmony_ci
954f08c3bdfSopenharmony_ciThe test-supplied cleanup function runs *concurrently* to the rest of the
955f08c3bdfSopenharmony_cithreads in a case that cleanup was entered from 'tst_brk()'. Subsequent
956f08c3bdfSopenharmony_cithreads entering 'tst_brk()' must be suspended or terminated at the start of
957f08c3bdfSopenharmony_cithe user supplied cleanup function. It may be necessary to stop or exit
958f08c3bdfSopenharmony_cithe rest of the threads before the test cleans up as well. For example threads
959f08c3bdfSopenharmony_cithat create new files should be stopped before temporary directory is be
960f08c3bdfSopenharmony_ciremoved.
961f08c3bdfSopenharmony_ci
962f08c3bdfSopenharmony_ciFollowing code example shows thread safe cleanup function example using atomic
963f08c3bdfSopenharmony_ciincrement as a guard. The library calls its cleanup after the execution returns
964f08c3bdfSopenharmony_cifrom the user supplied cleanup and expects that only one thread returns from
965f08c3bdfSopenharmony_cithe user supplied cleanup to the test library.
966f08c3bdfSopenharmony_ci
967f08c3bdfSopenharmony_ci[source,c]
968f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
969f08c3bdfSopenharmony_ci#include "tst_test.h"
970f08c3bdfSopenharmony_ci
971f08c3bdfSopenharmony_cistatic void cleanup(void)
972f08c3bdfSopenharmony_ci{
973f08c3bdfSopenharmony_ci	static int flag;
974f08c3bdfSopenharmony_ci
975f08c3bdfSopenharmony_ci	if (tst_atomic_inc(&flag) != 1)
976f08c3bdfSopenharmony_ci		pthread_exit(NULL);
977f08c3bdfSopenharmony_ci
978f08c3bdfSopenharmony_ci	/* if needed stop the rest of the threads here */
979f08c3bdfSopenharmony_ci
980f08c3bdfSopenharmony_ci	...
981f08c3bdfSopenharmony_ci
982f08c3bdfSopenharmony_ci	/* then do cleanup work */
983f08c3bdfSopenharmony_ci
984f08c3bdfSopenharmony_ci	...
985f08c3bdfSopenharmony_ci
986f08c3bdfSopenharmony_ci	/* only one thread returns to the library */
987f08c3bdfSopenharmony_ci}
988f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
989f08c3bdfSopenharmony_ci
990f08c3bdfSopenharmony_ci
991f08c3bdfSopenharmony_ci1.15 Testing with a block device
992f08c3bdfSopenharmony_ci~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
993f08c3bdfSopenharmony_ci
994f08c3bdfSopenharmony_ciSome tests needs a block device (inotify tests, syscall 'EROFS' failures,
995f08c3bdfSopenharmony_cietc.). LTP library contains a code to prepare a testing device.
996f08c3bdfSopenharmony_ci
997f08c3bdfSopenharmony_ciIf '.needs_device' flag in the 'struct tst_test' is set the 'tst_device'
998f08c3bdfSopenharmony_cistructure is initialized with a path to a test device and default filesystem
999f08c3bdfSopenharmony_cito be used.
1000f08c3bdfSopenharmony_ci
1001f08c3bdfSopenharmony_ciYou can also request minimal device size in megabytes by setting
1002f08c3bdfSopenharmony_ci'.dev_min_size' the device is guaranteed to have at least the requested size
1003f08c3bdfSopenharmony_cithen.
1004f08c3bdfSopenharmony_ci
1005f08c3bdfSopenharmony_ciIf '.format_device' flag is set the device is formatted with a filesystem as
1006f08c3bdfSopenharmony_ciwell. You can use '.dev_fs_type' to override the default filesystem type if
1007f08c3bdfSopenharmony_cineeded and pass additional options to mkfs via '.dev_fs_opts' and
1008f08c3bdfSopenharmony_ci'.dev_extra_opts' pointers. Note that '.format_device' implies '.needs_device'
1009f08c3bdfSopenharmony_cithere is no need to set both.
1010f08c3bdfSopenharmony_ci
1011f08c3bdfSopenharmony_ciIf '.mount_device' is set, the device is mounted at '.mntpoint' which is used
1012f08c3bdfSopenharmony_cito pass a directory name that will be created and used as mount destination.
1013f08c3bdfSopenharmony_ciYou can pass additional flags and data to the mount command via '.mnt_flags'
1014f08c3bdfSopenharmony_ciand '.mnt_data' pointers. Note that '.mount_device' implies '.needs_device'
1015f08c3bdfSopenharmony_ciand '.format_device' so there is no need to set the later two.
1016f08c3bdfSopenharmony_ci
1017f08c3bdfSopenharmony_ciIf '.needs_rofs' is set, read-only filesystem is mounted at '.mntpoint' this
1018f08c3bdfSopenharmony_cione is supposed to be used for 'EROFS' tests.
1019f08c3bdfSopenharmony_ci
1020f08c3bdfSopenharmony_ciIf '.all_filesystems' is set the test function is executed for all supported
1021f08c3bdfSopenharmony_cifilesystems. Supported filesystems are detected based on existence of the
1022f08c3bdfSopenharmony_ci'mkfs.$fs' helper and on kernel support to mount it. For each supported
1023f08c3bdfSopenharmony_cifilesystem the 'tst_device.fs_type' is set to the currently tested fs type, if
1024f08c3bdfSopenharmony_ci'.format_device' is set the device is formatted as well, if '.mount_device' is
1025f08c3bdfSopenharmony_ciset it's mounted at '.mntpoint'. Also the test timeout is reset for each
1026f08c3bdfSopenharmony_ciexecution of the test function. This flag is expected to be used for filesystem
1027f08c3bdfSopenharmony_cirelated syscalls that are at least partly implemented in the filesystem
1028f08c3bdfSopenharmony_cispecific code e.g. 'fallocate()'.
1029f08c3bdfSopenharmony_ci
1030f08c3bdfSopenharmony_ci[source,c]
1031f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
1032f08c3bdfSopenharmony_ci#include "tst_test.h"
1033f08c3bdfSopenharmony_ci
1034f08c3bdfSopenharmony_cistruct tst_device {
1035f08c3bdfSopenharmony_ci	const char *dev;
1036f08c3bdfSopenharmony_ci	const char *fs_type;
1037f08c3bdfSopenharmony_ci};
1038f08c3bdfSopenharmony_ci
1039f08c3bdfSopenharmony_ciextern struct tst_device *tst_device;
1040f08c3bdfSopenharmony_ci
1041f08c3bdfSopenharmony_ciint tst_umount(const char *path);
1042f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
1043f08c3bdfSopenharmony_ci
1044f08c3bdfSopenharmony_ciIn case that 'LTP_DEV' is passed to the test in an environment, the library
1045f08c3bdfSopenharmony_cichecks that the file exists and that it's a block device, if
1046f08c3bdfSopenharmony_ci'.device_min_size' is set the device size is checked as well. If 'LTP_DEV'
1047f08c3bdfSopenharmony_ciwasn't set or if size requirements were not met a temporary file is created
1048f08c3bdfSopenharmony_ciand attached to a free loop device.
1049f08c3bdfSopenharmony_ci
1050f08c3bdfSopenharmony_ciIf there is no usable device and loop device couldn't be initialized the test
1051f08c3bdfSopenharmony_ciexits with 'TCONF'.
1052f08c3bdfSopenharmony_ci
1053f08c3bdfSopenharmony_ciThe 'tst_umount()' function works exactly as 'umount(2)' but retries several
1054f08c3bdfSopenharmony_citimes on 'EBUSY'. This is because various desktop daemons (gvfsd-trash is known
1055f08c3bdfSopenharmony_cifor that) may be stupid enough to probe all newly mounted filesystem which
1056f08c3bdfSopenharmony_ciresults in 'umount(2)' failing with 'EBUSY'.
1057f08c3bdfSopenharmony_ci
1058f08c3bdfSopenharmony_ciIMPORTANT: All testcases should use 'tst_umount()' instead of 'umount(2)' to
1059f08c3bdfSopenharmony_ci           umount filesystems.
1060f08c3bdfSopenharmony_ci
1061f08c3bdfSopenharmony_ci[source,c]
1062f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
1063f08c3bdfSopenharmony_ci#include "tst_test.h"
1064f08c3bdfSopenharmony_ci
1065f08c3bdfSopenharmony_ciint tst_find_free_loopdev(const char *path, size_t path_len);
1066f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
1067f08c3bdfSopenharmony_ci
1068f08c3bdfSopenharmony_ciThis function finds a free loopdev and returns the free loopdev minor (-1 for no
1069f08c3bdfSopenharmony_cifree loopdev). If path is non-NULL, it will be filled with free loopdev path.
1070f08c3bdfSopenharmony_ciIf you want to use a customized loop device, we can call 'tst_find_free_loopdev(NULL, 0)'
1071f08c3bdfSopenharmony_ciin tests to get a free minor number and then mknod.
1072f08c3bdfSopenharmony_ci
1073f08c3bdfSopenharmony_ci[source,c]
1074f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
1075f08c3bdfSopenharmony_ci#include "tst_test.h"
1076f08c3bdfSopenharmony_ci
1077f08c3bdfSopenharmony_ciunsigned long tst_dev_bytes_written(const char *dev);
1078f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
1079f08c3bdfSopenharmony_ci
1080f08c3bdfSopenharmony_ciThis function reads test block device stat file ('/sys/block/<device>/stat') and
1081f08c3bdfSopenharmony_cireturns the bytes written since the last invocation of this function. To avoid
1082f08c3bdfSopenharmony_ciFS deferred IO metadata/cache interference, we suggest doing "syncfs" before the
1083f08c3bdfSopenharmony_citst_dev_bytes_written first invocation. And an inline function named 'tst_dev_sync()'
1084f08c3bdfSopenharmony_ciis created for that intention.
1085f08c3bdfSopenharmony_ci
1086f08c3bdfSopenharmony_ci[source,c]
1087f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
1088f08c3bdfSopenharmony_ci#include "tst_test.h"
1089f08c3bdfSopenharmony_ci
1090f08c3bdfSopenharmony_civoid tst_find_backing_dev(const char *path, char *dev, size_t dev_size);
1091f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
1092f08c3bdfSopenharmony_ci
1093f08c3bdfSopenharmony_ciThis function finds the block dev that this path belongs to, using uevent in sysfs.
1094f08c3bdfSopenharmony_ciFor Btrfs it uses '/sys/fs/btrfs/UUID/devices/DEV_NAME/uevent'; for other
1095f08c3bdfSopenharmony_cifilesystems it uses '/sys/dev/block/MAJOR:MINOR/uevent'.
1096f08c3bdfSopenharmony_ci
1097f08c3bdfSopenharmony_ci[source,c]
1098f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
1099f08c3bdfSopenharmony_ci#include "tst_test.h"
1100f08c3bdfSopenharmony_ci
1101f08c3bdfSopenharmony_ciuint64_t tst_get_device_size(const char *dev_path);
1102f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
1103f08c3bdfSopenharmony_ci
1104f08c3bdfSopenharmony_ciThis function gets size of the given block device, it checks the 'dev_path' is
1105f08c3bdfSopenharmony_civalid first, if yes, return the size in MB, otherwise return -1.
1106f08c3bdfSopenharmony_ci
1107f08c3bdfSopenharmony_ci[source,c]
1108f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
1109f08c3bdfSopenharmony_ci#include "tst_test.h"
1110f08c3bdfSopenharmony_ci
1111f08c3bdfSopenharmony_ciint tst_dev_block_size(const char *path);
1112f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
1113f08c3bdfSopenharmony_ci
1114f08c3bdfSopenharmony_ciThis function returns the physical device block size for the specific `path`.
1115f08c3bdfSopenharmony_ciIt finds the device where `path` is located and then uses `ioctl` (BLKSSZGET)
1116f08c3bdfSopenharmony_cito get a physical device block size.
1117f08c3bdfSopenharmony_ci
1118f08c3bdfSopenharmony_ci1.16 Formatting a device with a filesystem
1119f08c3bdfSopenharmony_ci~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1120f08c3bdfSopenharmony_ci
1121f08c3bdfSopenharmony_ci[source,c]
1122f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
1123f08c3bdfSopenharmony_ci#include "tst_test.h"
1124f08c3bdfSopenharmony_ci
1125f08c3bdfSopenharmony_cistatic void setup(void)
1126f08c3bdfSopenharmony_ci{
1127f08c3bdfSopenharmony_ci	...
1128f08c3bdfSopenharmony_ci	SAFE_MKFS(tst_device->dev, tst_device->fs_type, NULL, NULL);
1129f08c3bdfSopenharmony_ci	...
1130f08c3bdfSopenharmony_ci}
1131f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
1132f08c3bdfSopenharmony_ci
1133f08c3bdfSopenharmony_ciThis function takes a path to a device, filesystem type and an array of extra
1134f08c3bdfSopenharmony_cioptions passed to mkfs.
1135f08c3bdfSopenharmony_ci
1136f08c3bdfSopenharmony_ciThe fs options 'fs_opts' should either be 'NULL' if there are none, or a
1137f08c3bdfSopenharmony_ci'NULL' terminated array of strings such as:
1138f08c3bdfSopenharmony_ci+const char *const opts[] = {"-b", "1024", NULL}+.
1139f08c3bdfSopenharmony_ci
1140f08c3bdfSopenharmony_ciThe extra options 'extra_opts' should either be 'NULL' if there are none, or a
1141f08c3bdfSopenharmony_ci'NULL' terminated array of strings such as +{"102400", NULL}+; 'extra_opts'
1142f08c3bdfSopenharmony_ciwill be passed after device name. e.g: +mkfs -t ext4 -b 1024 /dev/sda1 102400+
1143f08c3bdfSopenharmony_ciin this case.
1144f08c3bdfSopenharmony_ci
1145f08c3bdfSopenharmony_ciNote that perfer to store the options which can be passed before or after device
1146f08c3bdfSopenharmony_ciname by 'fs_opts' array.
1147f08c3bdfSopenharmony_ci
1148f08c3bdfSopenharmony_ci1.17 Verifying a filesystem's free space
1149f08c3bdfSopenharmony_ci~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1150f08c3bdfSopenharmony_ci
1151f08c3bdfSopenharmony_ciSome tests have size requirements for the filesystem's free space. If these
1152f08c3bdfSopenharmony_cirequirements are not satisfied, the tests should be skipped.
1153f08c3bdfSopenharmony_ci
1154f08c3bdfSopenharmony_ci[source,c]
1155f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
1156f08c3bdfSopenharmony_ci#include "tst_test.h"
1157f08c3bdfSopenharmony_ci
1158f08c3bdfSopenharmony_ciint tst_fs_has_free(const char *path, unsigned int size, unsigned int mult);
1159f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
1160f08c3bdfSopenharmony_ci
1161f08c3bdfSopenharmony_ciThe 'tst_fs_has_free()' function returns 1 if there is enough space and 0 if
1162f08c3bdfSopenharmony_cithere is not.
1163f08c3bdfSopenharmony_ci
1164f08c3bdfSopenharmony_ciThe 'path' is the pathname of any directory/file within a filesystem.
1165f08c3bdfSopenharmony_ci
1166f08c3bdfSopenharmony_ciThe 'mult' is a multiplier, one of 'TST_BYTES', 'TST_KB', 'TST_MB' or 'TST_GB'.
1167f08c3bdfSopenharmony_ci
1168f08c3bdfSopenharmony_ciThe required free space is calculated by 'size * mult', e.g.
1169f08c3bdfSopenharmony_ci'tst_fs_has_free("/tmp/testfile", 64, TST_MB)' will return 1 if the
1170f08c3bdfSopenharmony_cifilesystem, which '"/tmp/testfile"' is in, has 64MB free space at least, and 0
1171f08c3bdfSopenharmony_ciif not.
1172f08c3bdfSopenharmony_ci
1173f08c3bdfSopenharmony_ci1.18 Files, directories and fs limits
1174f08c3bdfSopenharmony_ci~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1175f08c3bdfSopenharmony_ci
1176f08c3bdfSopenharmony_ciSome tests need to know the maximum count of links to a regular file or
1177f08c3bdfSopenharmony_cidirectory, such as 'rename(2)' or 'linkat(2)' to test 'EMLINK' error.
1178f08c3bdfSopenharmony_ci
1179f08c3bdfSopenharmony_ci[source,c]
1180f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
1181f08c3bdfSopenharmony_ci#include "tst_test.h"
1182f08c3bdfSopenharmony_ci
1183f08c3bdfSopenharmony_ciint tst_fs_fill_hardlinks(const char *dir);
1184f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
1185f08c3bdfSopenharmony_ci
1186f08c3bdfSopenharmony_ciTry to get maximum count of hard links to a regular file inside the 'dir'.
1187f08c3bdfSopenharmony_ci
1188f08c3bdfSopenharmony_ciNOTE: This number depends on the filesystem 'dir' is on.
1189f08c3bdfSopenharmony_ci
1190f08c3bdfSopenharmony_ciThis function uses 'link(2)' to create hard links to a single file until it
1191f08c3bdfSopenharmony_cigets 'EMLINK' or creates 65535 links. If the limit is hit, the maximum number of
1192f08c3bdfSopenharmony_cihardlinks is returned and the 'dir' is filled with hardlinks in format
1193f08c3bdfSopenharmony_ci"testfile%i", where i belongs to [0, limit) interval. If no limit is hit or if
1194f08c3bdfSopenharmony_ci'link(2)' failed with 'ENOSPC' or 'EDQUOT', zero is returned and previously
1195f08c3bdfSopenharmony_cicreated files are removed.
1196f08c3bdfSopenharmony_ci
1197f08c3bdfSopenharmony_ci[source,c]
1198f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
1199f08c3bdfSopenharmony_ci#include "tst_test.h"
1200f08c3bdfSopenharmony_ci
1201f08c3bdfSopenharmony_ciint tst_fs_fill_subdirs(const char *dir);
1202f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
1203f08c3bdfSopenharmony_ci
1204f08c3bdfSopenharmony_ciTry to get maximum number of subdirectories in directory.
1205f08c3bdfSopenharmony_ci
1206f08c3bdfSopenharmony_ciNOTE: This number depends on the filesystem 'dir' is on. For current kernel,
1207f08c3bdfSopenharmony_cisubdir limit is not available for all filesystems (available for ext2, ext3,
1208f08c3bdfSopenharmony_ciminix, sysv and more). If the test runs on some other filesystems, like ramfs,
1209f08c3bdfSopenharmony_citmpfs, it will not even try to reach the limit and return 0.
1210f08c3bdfSopenharmony_ci
1211f08c3bdfSopenharmony_ciThis function uses 'mkdir(2)' to create directories in 'dir' until it gets
1212f08c3bdfSopenharmony_ci'EMLINK' or creates 65535 directories. If the limit is hit, the maximum number
1213f08c3bdfSopenharmony_ciof subdirectories is returned and the 'dir' is filled with subdirectories in
1214f08c3bdfSopenharmony_ciformat "testdir%i", where i belongs to [0, limit - 2) interval (because each
1215f08c3bdfSopenharmony_cinewly created dir has two links already - the '.' and the link from parent
1216f08c3bdfSopenharmony_cidir). If no limit is hit or if 'mkdir(2)' failed with 'ENOSPC' or 'EDQUOT',
1217f08c3bdfSopenharmony_cizero is returned and previously created directories are removed.
1218f08c3bdfSopenharmony_ci
1219f08c3bdfSopenharmony_ci[source,c]
1220f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
1221f08c3bdfSopenharmony_ci#include "tst_test.h"
1222f08c3bdfSopenharmony_ci
1223f08c3bdfSopenharmony_ciint tst_dir_is_empty(const char *dir, int verbose);
1224f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
1225f08c3bdfSopenharmony_ci
1226f08c3bdfSopenharmony_ciReturns non-zero if directory is empty and zero otherwise.
1227f08c3bdfSopenharmony_ci
1228f08c3bdfSopenharmony_ciDirectory is considered empty if it contains only '.' and '..'.
1229f08c3bdfSopenharmony_ci
1230f08c3bdfSopenharmony_ci[source,c]
1231f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
1232f08c3bdfSopenharmony_ci#include "tst_test.h"
1233f08c3bdfSopenharmony_ci
1234f08c3bdfSopenharmony_civoid tst_purge_dir(const char *path);
1235f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
1236f08c3bdfSopenharmony_ci
1237f08c3bdfSopenharmony_ciDeletes the contents of given directory but keeps the directory itself. Useful
1238f08c3bdfSopenharmony_cifor cleaning up the temporary directory and mount points between test cases or
1239f08c3bdfSopenharmony_citest iterations. Terminates the program with 'TBROK' on error.
1240f08c3bdfSopenharmony_ci
1241f08c3bdfSopenharmony_ci[source,c]
1242f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
1243f08c3bdfSopenharmony_ci#include "tst_test.h"
1244f08c3bdfSopenharmony_ci
1245f08c3bdfSopenharmony_ciint tst_fill_fd(int fd, char pattern, size_t bs, size_t bcount);
1246f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
1247f08c3bdfSopenharmony_ci
1248f08c3bdfSopenharmony_ciFill a file with specified pattern using file descriptor.
1249f08c3bdfSopenharmony_ci
1250f08c3bdfSopenharmony_ci[source,c]
1251f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
1252f08c3bdfSopenharmony_ci#include "tst_test.h"
1253f08c3bdfSopenharmony_ci
1254f08c3bdfSopenharmony_ciint tst_prealloc_size_fd(int fd, size_t bs, size_t bcount);
1255f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
1256f08c3bdfSopenharmony_ci
1257f08c3bdfSopenharmony_ciPreallocate the specified amount of space using 'fallocate()'. Falls back to
1258f08c3bdfSopenharmony_ci'tst_fill_fd()' if 'fallocate()' fails.
1259f08c3bdfSopenharmony_ci
1260f08c3bdfSopenharmony_ci[source,c]
1261f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
1262f08c3bdfSopenharmony_ci#include "tst_test.h"
1263f08c3bdfSopenharmony_ci
1264f08c3bdfSopenharmony_ciint tst_fill_file(const char *path, char pattern, size_t bs, size_t bcount);
1265f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
1266f08c3bdfSopenharmony_ci
1267f08c3bdfSopenharmony_ciCreates/overwrites a file with specified pattern using file path.
1268f08c3bdfSopenharmony_ci
1269f08c3bdfSopenharmony_ci[source,c]
1270f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
1271f08c3bdfSopenharmony_ci#include "tst_test.h"
1272f08c3bdfSopenharmony_ci
1273f08c3bdfSopenharmony_ciint tst_prealloc_file(const char *path, size_t bs, size_t bcount);
1274f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
1275f08c3bdfSopenharmony_ci
1276f08c3bdfSopenharmony_ciCreate/overwrite a file and preallocate the specified amount of space for it.
1277f08c3bdfSopenharmony_ciThe allocated space will not be initialized to any particular content.
1278f08c3bdfSopenharmony_ci
1279f08c3bdfSopenharmony_ci1.19 Getting an unused PID number
1280f08c3bdfSopenharmony_ci~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1281f08c3bdfSopenharmony_ci
1282f08c3bdfSopenharmony_ciSome tests require a 'PID', which is not used by the OS (does not belong to
1283f08c3bdfSopenharmony_ciany process within it). For example, kill(2) should set errno to 'ESRCH' if
1284f08c3bdfSopenharmony_ciit's passed such 'PID'.
1285f08c3bdfSopenharmony_ci
1286f08c3bdfSopenharmony_ci[source,c]
1287f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
1288f08c3bdfSopenharmony_ci#include "tst_test.h"
1289f08c3bdfSopenharmony_ci
1290f08c3bdfSopenharmony_cipid_t tst_get_unused_pid(void);
1291f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
1292f08c3bdfSopenharmony_ci
1293f08c3bdfSopenharmony_ciReturn a 'PID' value not used by the OS or any process within it.
1294f08c3bdfSopenharmony_ci
1295f08c3bdfSopenharmony_ci[source,c]
1296f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
1297f08c3bdfSopenharmony_ci#include "tst_test.h"
1298f08c3bdfSopenharmony_ci
1299f08c3bdfSopenharmony_ciint tst_get_free_pids(void);
1300f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
1301f08c3bdfSopenharmony_ci
1302f08c3bdfSopenharmony_ciReturns number of unused pids in the system. Note that this number may be
1303f08c3bdfSopenharmony_cidifferent once the call returns and should be used only for rough estimates.
1304f08c3bdfSopenharmony_ci
1305f08c3bdfSopenharmony_ci1.20 Running executables
1306f08c3bdfSopenharmony_ci~~~~~~~~~~~~~~~~~~~~~~~~
1307f08c3bdfSopenharmony_ci
1308f08c3bdfSopenharmony_ci[source,c]
1309f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
1310f08c3bdfSopenharmony_ci#include "tst_test.h"
1311f08c3bdfSopenharmony_ci
1312f08c3bdfSopenharmony_ciint tst_cmd(const char *const argv[],
1313f08c3bdfSopenharmony_ci	        const char *stdout_path,
1314f08c3bdfSopenharmony_ci	        const char *stderr_path,
1315f08c3bdfSopenharmony_ci	        enum tst_cmd_flags flags);
1316f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
1317f08c3bdfSopenharmony_ci
1318f08c3bdfSopenharmony_ci'tst_cmd()' is a wrapper for 'vfork() + execvp()' which provides a way
1319f08c3bdfSopenharmony_cito execute an external program.
1320f08c3bdfSopenharmony_ci
1321f08c3bdfSopenharmony_ci'argv[]' is a 'NULL' terminated array of strings starting with the program name
1322f08c3bdfSopenharmony_ciwhich is followed by optional arguments.
1323f08c3bdfSopenharmony_ci
1324f08c3bdfSopenharmony_ci'TST_CMD_PASS_RETVAL' enum 'tst_cmd_flags' makes 'tst_cmd()'
1325f08c3bdfSopenharmony_cireturn the program exit code to the caller, otherwise 'tst_cmd()' exit the
1326f08c3bdfSopenharmony_citests on failure. 'TST_CMD_TCONF_ON_MISSING' check for program in '$PATH' and exit
1327f08c3bdfSopenharmony_ciwith 'TCONF' if not found.
1328f08c3bdfSopenharmony_ci
1329f08c3bdfSopenharmony_ciIn case that 'execvp()' has failed and the enum 'TST_CMD_PASS_RETVAL' flag was set, the
1330f08c3bdfSopenharmony_cireturn value is '255' if 'execvp()' failed with 'ENOENT' and '254' otherwise.
1331f08c3bdfSopenharmony_ci
1332f08c3bdfSopenharmony_ci'stdout_path' and 'stderr_path' determine where to redirect the program
1333f08c3bdfSopenharmony_cistdout and stderr I/O streams.
1334f08c3bdfSopenharmony_ci
1335f08c3bdfSopenharmony_ciThe 'SAFE_CMD()' macro can be used automatic handling non-zero exits (exits
1336f08c3bdfSopenharmony_ciwith 'TBROK') and 'ENOENT' (exits with 'TCONF').
1337f08c3bdfSopenharmony_ci
1338f08c3bdfSopenharmony_ci.Example
1339f08c3bdfSopenharmony_ci[source,c]
1340f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
1341f08c3bdfSopenharmony_ci#include "tst_test.h"
1342f08c3bdfSopenharmony_ci
1343f08c3bdfSopenharmony_ciconst char *const cmd[] = { "ls", "-l", NULL };
1344f08c3bdfSopenharmony_ci
1345f08c3bdfSopenharmony_ci...
1346f08c3bdfSopenharmony_ci	/* Store output of 'ls -l' into log.txt */
1347f08c3bdfSopenharmony_ci	tst_cmd(cmd, "log.txt", NULL, 0);
1348f08c3bdfSopenharmony_ci...
1349f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
1350f08c3bdfSopenharmony_ci
1351f08c3bdfSopenharmony_ci1.21 Measuring elapsed time and helper functions
1352f08c3bdfSopenharmony_ci~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1353f08c3bdfSopenharmony_ci
1354f08c3bdfSopenharmony_ci[source,c]
1355f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
1356f08c3bdfSopenharmony_ci#include "tst_timer.h"
1357f08c3bdfSopenharmony_ci
1358f08c3bdfSopenharmony_civoid tst_timer_check(clockid_t clk_id);
1359f08c3bdfSopenharmony_ci
1360f08c3bdfSopenharmony_civoid tst_timer_start(clockid_t clk_id);
1361f08c3bdfSopenharmony_ci
1362f08c3bdfSopenharmony_civoid tst_timer_stop(void);
1363f08c3bdfSopenharmony_ci
1364f08c3bdfSopenharmony_cistruct timespec tst_timer_elapsed(void);
1365f08c3bdfSopenharmony_ci
1366f08c3bdfSopenharmony_cilong long tst_timer_elapsed_ms(void);
1367f08c3bdfSopenharmony_ci
1368f08c3bdfSopenharmony_cilong long tst_timer_elapsed_us(void);
1369f08c3bdfSopenharmony_ci
1370f08c3bdfSopenharmony_ciint tst_timer_expired_ms(long long ms);
1371f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
1372f08c3bdfSopenharmony_ci
1373f08c3bdfSopenharmony_ciThe 'tst_timer_check()' function checks if specified 'clk_id' is supported and
1374f08c3bdfSopenharmony_ciexits the test with 'TCONF' otherwise. It's expected to be used in test
1375f08c3bdfSopenharmony_ci'setup()' before any resources that needs to be cleaned up are initialized,
1376f08c3bdfSopenharmony_cihence it does not include a cleanup function parameter.
1377f08c3bdfSopenharmony_ci
1378f08c3bdfSopenharmony_ciThe 'tst_timer_start()' marks start time and stores the 'clk_id' for further
1379f08c3bdfSopenharmony_ciuse.
1380f08c3bdfSopenharmony_ci
1381f08c3bdfSopenharmony_ciThe 'tst_timer_stop()' marks the stop time using the same 'clk_id' as last
1382f08c3bdfSopenharmony_cicall to 'tst_timer_start()'.
1383f08c3bdfSopenharmony_ci
1384f08c3bdfSopenharmony_ciThe 'tst_timer_elapsed*()' returns time difference between the timer start and
1385f08c3bdfSopenharmony_cilast timer stop in several formats and units.
1386f08c3bdfSopenharmony_ci
1387f08c3bdfSopenharmony_ciThe 'tst_timer_expired_ms()' function checks if the timer started by
1388f08c3bdfSopenharmony_ci'tst_timer_start()' has been running longer than ms milliseconds. The function
1389f08c3bdfSopenharmony_cireturns non-zero if timer has expired and zero otherwise.
1390f08c3bdfSopenharmony_ci
1391f08c3bdfSopenharmony_ciIMPORTANT: The timer functions use 'clock_gettime()' internally which needs to
1392f08c3bdfSopenharmony_ci           be linked with '-lrt' on older glibc. Please do not forget to add
1393f08c3bdfSopenharmony_ci	   'LDLIBS+=-lrt' in Makefile.
1394f08c3bdfSopenharmony_ci
1395f08c3bdfSopenharmony_ci[source,c]
1396f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
1397f08c3bdfSopenharmony_ci#include "tst_test.h"
1398f08c3bdfSopenharmony_ci#include "tst_timer.h"
1399f08c3bdfSopenharmony_ci
1400f08c3bdfSopenharmony_cistatic void setup(void)
1401f08c3bdfSopenharmony_ci{
1402f08c3bdfSopenharmony_ci	...
1403f08c3bdfSopenharmony_ci	tst_timer_check(CLOCK_MONOTONIC);
1404f08c3bdfSopenharmony_ci	...
1405f08c3bdfSopenharmony_ci}
1406f08c3bdfSopenharmony_ci
1407f08c3bdfSopenharmony_cistatic void run(void)
1408f08c3bdfSopenharmony_ci{
1409f08c3bdfSopenharmony_ci	...
1410f08c3bdfSopenharmony_ci	tst_timer_start(CLOCK_MONOTONIC);
1411f08c3bdfSopenharmony_ci	...
1412f08c3bdfSopenharmony_ci	while (!tst_timer_expired_ms(5000)) {
1413f08c3bdfSopenharmony_ci		...
1414f08c3bdfSopenharmony_ci	}
1415f08c3bdfSopenharmony_ci	...
1416f08c3bdfSopenharmony_ci}
1417f08c3bdfSopenharmony_ci
1418f08c3bdfSopenharmony_cistruct tst_test test = {
1419f08c3bdfSopenharmony_ci	...
1420f08c3bdfSopenharmony_ci	.setup = setup,
1421f08c3bdfSopenharmony_ci	.test_all = run,
1422f08c3bdfSopenharmony_ci	...
1423f08c3bdfSopenharmony_ci};
1424f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
1425f08c3bdfSopenharmony_ci
1426f08c3bdfSopenharmony_ciExpiration timer example usage.
1427f08c3bdfSopenharmony_ci
1428f08c3bdfSopenharmony_ci[source,c]
1429f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
1430f08c3bdfSopenharmony_cilong long tst_timespec_to_us(struct timespec t);
1431f08c3bdfSopenharmony_cilong long tst_timespec_to_ms(struct timespec t);
1432f08c3bdfSopenharmony_ci
1433f08c3bdfSopenharmony_cistruct timeval tst_us_to_timeval(long long us);
1434f08c3bdfSopenharmony_cistruct timeval tst_ms_to_timeval(long long ms);
1435f08c3bdfSopenharmony_ci
1436f08c3bdfSopenharmony_ciint tst_timespec_lt(struct timespec t1, struct timespec t2);
1437f08c3bdfSopenharmony_ci
1438f08c3bdfSopenharmony_cistruct timespec tst_timespec_add_us(struct timespec t, long long us);
1439f08c3bdfSopenharmony_ci
1440f08c3bdfSopenharmony_cistruct timespec tst_timespec_diff(struct timespec t1, struct timespec t2);
1441f08c3bdfSopenharmony_cilong long tst_timespec_diff_us(struct timespec t1, struct timespec t2);
1442f08c3bdfSopenharmony_cilong long tst_timespec_diff_ms(struct timespec t1, struct timespec t2);
1443f08c3bdfSopenharmony_ci
1444f08c3bdfSopenharmony_cistruct timespec tst_timespec_abs_diff(struct timespec t1, struct timespec t2);
1445f08c3bdfSopenharmony_cilong long tst_timespec_abs_diff_us(struct timespec t1, struct timespec t2);
1446f08c3bdfSopenharmony_cilong long tst_timespec_abs_diff_ms(struct timespec t1, struct timespec t2);
1447f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
1448f08c3bdfSopenharmony_ci
1449f08c3bdfSopenharmony_ciThe first four functions are simple inline conversion functions.
1450f08c3bdfSopenharmony_ci
1451f08c3bdfSopenharmony_ciThe 'tst_timespec_lt()' function returns non-zero if 't1' is earlier than
1452f08c3bdfSopenharmony_ci't2'.
1453f08c3bdfSopenharmony_ci
1454f08c3bdfSopenharmony_ciThe 'tst_timespec_add_us()' function adds 'us' microseconds to the timespec
1455f08c3bdfSopenharmony_ci't'. The 'us' is expected to be positive.
1456f08c3bdfSopenharmony_ci
1457f08c3bdfSopenharmony_ciThe 'tst_timespec_diff*()' functions returns difference between two times, the
1458f08c3bdfSopenharmony_ci't1' is expected to be later than 't2'.
1459f08c3bdfSopenharmony_ci
1460f08c3bdfSopenharmony_ciThe 'tst_timespec_abs_diff*()' functions returns absolute value of difference
1461f08c3bdfSopenharmony_cibetween two times.
1462f08c3bdfSopenharmony_ci
1463f08c3bdfSopenharmony_ciNOTE: All conversions to ms and us rounds the value.
1464f08c3bdfSopenharmony_ci
1465f08c3bdfSopenharmony_ci1.22 Datafiles
1466f08c3bdfSopenharmony_ci~~~~~~~~~~~~~~
1467f08c3bdfSopenharmony_ci
1468f08c3bdfSopenharmony_ci[source,c]
1469f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
1470f08c3bdfSopenharmony_ci#include "tst_test.h"
1471f08c3bdfSopenharmony_ci
1472f08c3bdfSopenharmony_cistatic const char *const res_files[] = {
1473f08c3bdfSopenharmony_ci	"foo",
1474f08c3bdfSopenharmony_ci	"bar",
1475f08c3bdfSopenharmony_ci	NULL
1476f08c3bdfSopenharmony_ci};
1477f08c3bdfSopenharmony_ci
1478f08c3bdfSopenharmony_cistatic struct tst_test test = {
1479f08c3bdfSopenharmony_ci	...
1480f08c3bdfSopenharmony_ci	.resource_files = res_files,
1481f08c3bdfSopenharmony_ci	...
1482f08c3bdfSopenharmony_ci}
1483f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
1484f08c3bdfSopenharmony_ci
1485f08c3bdfSopenharmony_ciIf the test needs additional files to be copied to the test temporary
1486f08c3bdfSopenharmony_cidirectory all you need to do is to list their filenames in the
1487f08c3bdfSopenharmony_ci'NULL' terminated array '.resource_files' in the tst_test structure.
1488f08c3bdfSopenharmony_ci
1489f08c3bdfSopenharmony_ciWhen resource files is set test temporary directory is created automatically,
1490f08c3bdfSopenharmony_cithere is need to set '.needs_tmpdir' as well.
1491f08c3bdfSopenharmony_ci
1492f08c3bdfSopenharmony_ciThe test library looks for datafiles first, these are either stored in a
1493f08c3bdfSopenharmony_cidirectory called +datafiles+ in the +$PWD+ at the start of the test or in
1494f08c3bdfSopenharmony_ci+$LTPROOT/testcases/data/${test_binary_name}+. If the file is not found the
1495f08c3bdfSopenharmony_cilibrary looks into +$LTPROOT/testcases/bin/+ and to +$PWD+ at the start of the
1496f08c3bdfSopenharmony_citest. This ensures that the testcases can copy the file(s) effortlessly both
1497f08c3bdfSopenharmony_ciwhen test is started from the directory it was compiled in as well as when LTP
1498f08c3bdfSopenharmony_ciwas installed.
1499f08c3bdfSopenharmony_ci
1500f08c3bdfSopenharmony_ciThe file(s) are copied to the newly created test temporary directory which is
1501f08c3bdfSopenharmony_ciset as the test working directory when the 'test()' functions is executed.
1502f08c3bdfSopenharmony_ci
1503f08c3bdfSopenharmony_ci1.23 Code path tracing
1504f08c3bdfSopenharmony_ci~~~~~~~~~~~~~~~~~~~~~~
1505f08c3bdfSopenharmony_ci
1506f08c3bdfSopenharmony_ci'tst_res' is a macro, so on when you define a function in one file:
1507f08c3bdfSopenharmony_ci
1508f08c3bdfSopenharmony_ci[source,c]
1509f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
1510f08c3bdfSopenharmony_ciint do_action(int arg)
1511f08c3bdfSopenharmony_ci{
1512f08c3bdfSopenharmony_ci	...
1513f08c3bdfSopenharmony_ci
1514f08c3bdfSopenharmony_ci	if (ok) {
1515f08c3bdfSopenharmony_ci		tst_res(TPASS, "check passed");
1516f08c3bdfSopenharmony_ci		return 0;
1517f08c3bdfSopenharmony_ci	} else {
1518f08c3bdfSopenharmony_ci		tst_res(TFAIL, "check failed");
1519f08c3bdfSopenharmony_ci		return -1;
1520f08c3bdfSopenharmony_ci	}
1521f08c3bdfSopenharmony_ci}
1522f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
1523f08c3bdfSopenharmony_ci
1524f08c3bdfSopenharmony_ciand call it from another file, the file and line reported by 'tst_res' in this
1525f08c3bdfSopenharmony_cifunction will be from the former file.
1526f08c3bdfSopenharmony_ci
1527f08c3bdfSopenharmony_ci'TST_TRACE' can make the analysis of such situations easier. It's a macro which
1528f08c3bdfSopenharmony_ciinserts a call to 'tst_res(TINFO, ...)' in case its argument evaluates to
1529f08c3bdfSopenharmony_cinon-zero. In this call to 'tst_res(TINFO, ...)' the file and line will be
1530f08c3bdfSopenharmony_ciexpanded using the actual location of 'TST_TRACE'.
1531f08c3bdfSopenharmony_ci
1532f08c3bdfSopenharmony_ciFor example, if this another file contains:
1533f08c3bdfSopenharmony_ci
1534f08c3bdfSopenharmony_ci[source,c]
1535f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
1536f08c3bdfSopenharmony_ci#include "tst_test.h"
1537f08c3bdfSopenharmony_ci
1538f08c3bdfSopenharmony_ciif (TST_TRACE(do_action(arg))) {
1539f08c3bdfSopenharmony_ci	...
1540f08c3bdfSopenharmony_ci}
1541f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
1542f08c3bdfSopenharmony_ci
1543f08c3bdfSopenharmony_cithe generated output may look similar to:
1544f08c3bdfSopenharmony_ci
1545f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
1546f08c3bdfSopenharmony_cicommon.h:9: FAIL: check failed
1547f08c3bdfSopenharmony_citest.c:8: INFO: do_action(arg) failed
1548f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
1549f08c3bdfSopenharmony_ci
1550f08c3bdfSopenharmony_ci1.24 Tainted kernels
1551f08c3bdfSopenharmony_ci~~~~~~~~~~~~~~~~~~~~
1552f08c3bdfSopenharmony_ci
1553f08c3bdfSopenharmony_ciIf you need to detect whether a testcase triggers a kernel warning, bug or
1554f08c3bdfSopenharmony_cioops, the following can be used to detect TAINT_W or TAINT_D:
1555f08c3bdfSopenharmony_ci
1556f08c3bdfSopenharmony_ci[source,c]
1557f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
1558f08c3bdfSopenharmony_ci#include "tst_test.h"
1559f08c3bdfSopenharmony_ci
1560f08c3bdfSopenharmony_cistatic struct tst_test test = {
1561f08c3bdfSopenharmony_ci	...
1562f08c3bdfSopenharmony_ci	.taint_check = TST_TAINT_W | TST_TAINT_D,
1563f08c3bdfSopenharmony_ci	...
1564f08c3bdfSopenharmony_ci};
1565f08c3bdfSopenharmony_ci
1566f08c3bdfSopenharmony_civoid run(void)
1567f08c3bdfSopenharmony_ci{
1568f08c3bdfSopenharmony_ci	...
1569f08c3bdfSopenharmony_ci	if (tst_taint_check() != 0)
1570f08c3bdfSopenharmony_ci		tst_res(TFAIL, "kernel has issues");
1571f08c3bdfSopenharmony_ci	else
1572f08c3bdfSopenharmony_ci		tst_res(TPASS, "kernel seems to be fine");
1573f08c3bdfSopenharmony_ci}
1574f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
1575f08c3bdfSopenharmony_ci
1576f08c3bdfSopenharmony_ciTo initialize taint checks, you have to set the taint flags you want to test
1577f08c3bdfSopenharmony_cifor in the 'taint_check' attribute of the tst_test struct. LTP library will
1578f08c3bdfSopenharmony_cithen automatically call 'tst_taint_init()' during test setup. The function
1579f08c3bdfSopenharmony_ciwill generate a 'TCONF' if the requested flags are not fully supported on the
1580f08c3bdfSopenharmony_cirunning kernel, and 'TBROK' if the kernel is already tainted before executing
1581f08c3bdfSopenharmony_cithe test.
1582f08c3bdfSopenharmony_ci
1583f08c3bdfSopenharmony_ciLTP library will then automatically check kernel taint at the end of testing.
1584f08c3bdfSopenharmony_ciIf '.all_filesystems' is set in struct tst_test, taint check will be performed
1585f08c3bdfSopenharmony_ciafter each file system and taint will abort testing early with 'TFAIL'. You
1586f08c3bdfSopenharmony_cican optionally also call 'tst_taint_check()' during 'run()', which returns 0
1587f08c3bdfSopenharmony_cior the tainted flags set in '/proc/sys/kernel/tainted' as specified earlier.
1588f08c3bdfSopenharmony_ci
1589f08c3bdfSopenharmony_ciDepending on your kernel version, not all tainted-flags will be supported.
1590f08c3bdfSopenharmony_ci
1591f08c3bdfSopenharmony_ciFor reference to tainted kernels, see kernel documentation:
1592f08c3bdfSopenharmony_ciDocumentation/admin-guide/tainted-kernels.rst or
1593f08c3bdfSopenharmony_cihttps://www.kernel.org/doc/html/latest/admin-guide/tainted-kernels.html
1594f08c3bdfSopenharmony_ci
1595f08c3bdfSopenharmony_ci1.25 Checksums
1596f08c3bdfSopenharmony_ci~~~~~~~~~~~~~~
1597f08c3bdfSopenharmony_ci
1598f08c3bdfSopenharmony_ciCRC32c checksum generation is supported by LTP. In order to use it, the
1599f08c3bdfSopenharmony_citest should include 'tst_checksum.h' header, then can call 'tst_crc32c()'.
1600f08c3bdfSopenharmony_ci
1601f08c3bdfSopenharmony_ci1.26 Checking kernel for the driver support
1602f08c3bdfSopenharmony_ci~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1603f08c3bdfSopenharmony_ci
1604f08c3bdfSopenharmony_ciSome tests may need specific kernel drivers, either compiled in, or built
1605f08c3bdfSopenharmony_cias a module. If '.needs_drivers' points to a 'NULL' terminated array of kernel
1606f08c3bdfSopenharmony_cimodule names these are all checked and the test exits with 'TCONF' on the
1607f08c3bdfSopenharmony_cifirst missing driver.
1608f08c3bdfSopenharmony_ci
1609f08c3bdfSopenharmony_ciThe detection is based on reading 'modules.dep' and 'modules.builtin' files
1610f08c3bdfSopenharmony_cigenerated by kmod. The check is skipped on Android.
1611f08c3bdfSopenharmony_ci
1612f08c3bdfSopenharmony_ci1.27 Saving & restoring /proc|sys values
1613f08c3bdfSopenharmony_ci~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1614f08c3bdfSopenharmony_ci
1615f08c3bdfSopenharmony_ciLTP library can be instructed to save and restore value of specified
1616f08c3bdfSopenharmony_ci(/proc|sys) files. This is achieved by initialized tst_test struct
1617f08c3bdfSopenharmony_cifield 'save_restore'. It is a NULL-terminated array of struct
1618f08c3bdfSopenharmony_ci'tst_path_val' where each tst_path_val.path represents a file, whose
1619f08c3bdfSopenharmony_civalue is saved at the beginning and restored at the end of the test.
1620f08c3bdfSopenharmony_ciIf non-NULL string is passed in tst_path_val.val, it is written
1621f08c3bdfSopenharmony_cito the respective file at the beginning of the test. Only the first line
1622f08c3bdfSopenharmony_ciof a specified file is saved and restored.
1623f08c3bdfSopenharmony_ci
1624f08c3bdfSopenharmony_ciBy default, the test will end with TCONF if the file is read-only or
1625f08c3bdfSopenharmony_cidoes not exist. If the optional write of new value fails, the test will end
1626f08c3bdfSopenharmony_ciwith 'TBROK'. This behavior can be changed using tst_path_val.flags:
1627f08c3bdfSopenharmony_ci
1628f08c3bdfSopenharmony_ci* 'TST_SR_TBROK_MISSING' – End test with 'TBROK' if the file does not exist
1629f08c3bdfSopenharmony_ci* 'TST_SR_TCONF_MISSING' – End test with 'TCONF' if the file does not exist
1630f08c3bdfSopenharmony_ci* 'TST_SR_SKIP_MISSING' – Continue without saving the file if it does not exist
1631f08c3bdfSopenharmony_ci* 'TST_SR_TBROK_RO' – End test with 'TBROK' if the file is read-only
1632f08c3bdfSopenharmony_ci* 'TST_SR_TCONF_RO' – End test with 'TCONF' if the file is read-only
1633f08c3bdfSopenharmony_ci* 'TST_SR_SKIP_RO' – Continue without saving the file if it is read-only
1634f08c3bdfSopenharmony_ci* 'TST_SR_IGNORE_ERR' – Ignore errors when writing new value into the file
1635f08c3bdfSopenharmony_ci
1636f08c3bdfSopenharmony_ciCommon flag combinations also have shortcuts:
1637f08c3bdfSopenharmony_ci
1638f08c3bdfSopenharmony_ci* 'TST_SR_TCONF' – Equivalent to 'TST_SR_TCONF_MISSING | TST_SR_TCONF_RO'
1639f08c3bdfSopenharmony_ci* 'TST_SR_TBROK' – Equivalent to 'TST_SR_TBROK_MISSING | TST_SR_TBROK_RO'
1640f08c3bdfSopenharmony_ci* 'TST_SR_SKIP' – Equivalent to 'TST_SR_SKIP_MISSING | TST_SR_SKIP_RO'
1641f08c3bdfSopenharmony_ci
1642f08c3bdfSopenharmony_ci'restore' is always strict and will TWARN if it encounters any error.
1643f08c3bdfSopenharmony_ci
1644f08c3bdfSopenharmony_ci[source,c]
1645f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
1646f08c3bdfSopenharmony_cistatic struct tst_test test = {
1647f08c3bdfSopenharmony_ci	...
1648f08c3bdfSopenharmony_ci	.setup = setup,
1649f08c3bdfSopenharmony_ci	.save_restore = (const struct tst_path_val[]) {
1650f08c3bdfSopenharmony_ci		{"/proc/sys/kernel/core_pattern", NULL, TST_SR_TCONF},
1651f08c3bdfSopenharmony_ci		{"/proc/sys/user/max_user_namespaces", NULL, TST_SR_SKIP},
1652f08c3bdfSopenharmony_ci		{"/sys/kernel/mm/ksm/run", "1", TST_SR_TBROK},
1653f08c3bdfSopenharmony_ci		{}
1654f08c3bdfSopenharmony_ci	},
1655f08c3bdfSopenharmony_ci};
1656f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
1657f08c3bdfSopenharmony_ci
1658f08c3bdfSopenharmony_ci1.28 Parsing kernel .config
1659f08c3bdfSopenharmony_ci~~~~~~~~~~~~~~~~~~~~~~~~~~~
1660f08c3bdfSopenharmony_ci
1661f08c3bdfSopenharmony_ciGenerally testcases should attempt to autodetect as much kernel features as
1662f08c3bdfSopenharmony_cipossible based on the currently running kernel. We do have tst_check_driver()
1663f08c3bdfSopenharmony_cito check if functionality that could be compiled as kernel module is present
1664f08c3bdfSopenharmony_cion the system, disabled syscalls can be detected by checking for 'ENOSYS'
1665f08c3bdfSopenharmony_cierrno etc.
1666f08c3bdfSopenharmony_ci
1667f08c3bdfSopenharmony_ciHowever in rare cases core kernel features couldn't be detected based on the
1668f08c3bdfSopenharmony_cikernel userspace API and we have to resort to parse the kernel .config.
1669f08c3bdfSopenharmony_ci
1670f08c3bdfSopenharmony_ciFor this cases the test should set the 'NULL' terminated '.needs_kconfigs'
1671f08c3bdfSopenharmony_ciarray of boolean expressions with constraints on the kconfig variables. The
1672f08c3bdfSopenharmony_ciboolean expression consits of variables, two binary operations '&' and '|',
1673f08c3bdfSopenharmony_cinegation '!' and correct sequence of parentesis '()'. Variables are expected
1674f08c3bdfSopenharmony_cito be in a form of "CONFIG_FOO[=bar]".
1675f08c3bdfSopenharmony_ci
1676f08c3bdfSopenharmony_ciThe test will continue to run if all expressions are evaluated to 'True'.
1677f08c3bdfSopenharmony_ciMissing variable is mapped to 'False' as well as variable with different than
1678f08c3bdfSopenharmony_cispecified value, e.g. 'CONFIG_FOO=bar' will evaluate to 'False' if the value
1679f08c3bdfSopenharmony_ciis anything else but 'bar'. If config variable is specified as plain
1680f08c3bdfSopenharmony_ci'CONFIG_FOO' it's evaluated to true it's set to any value (typically =y or =m).
1681f08c3bdfSopenharmony_ci
1682f08c3bdfSopenharmony_ci[source,c]
1683f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
1684f08c3bdfSopenharmony_ci#include "tst_test.h"
1685f08c3bdfSopenharmony_ci
1686f08c3bdfSopenharmony_cistatic const char *kconfigs[] = {
1687f08c3bdfSopenharmony_ci	"CONFIG_X86_INTEL_UMIP | CONFIG_X86_UMIP",
1688f08c3bdfSopenharmony_ci	NULL
1689f08c3bdfSopenharmony_ci};
1690f08c3bdfSopenharmony_ci
1691f08c3bdfSopenharmony_cistatic struct tst_test test = {
1692f08c3bdfSopenharmony_ci	...
1693f08c3bdfSopenharmony_ci	.needs_kconfigs = kconfigs,
1694f08c3bdfSopenharmony_ci	...
1695f08c3bdfSopenharmony_ci};
1696f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
1697f08c3bdfSopenharmony_ci
1698f08c3bdfSopenharmony_ci1.29 Changing the Wall Clock Time during test execution
1699f08c3bdfSopenharmony_ci~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1700f08c3bdfSopenharmony_ci
1701f08c3bdfSopenharmony_ciThere are some tests that, for different reasons, might need to change the
1702f08c3bdfSopenharmony_cisystem-wide clock time. Whenever this happens, it is imperative that the clock
1703f08c3bdfSopenharmony_ciis restored, at the end of test's execution, taking in consideration the amount
1704f08c3bdfSopenharmony_ciof time elapsed during that test.
1705f08c3bdfSopenharmony_ci
1706f08c3bdfSopenharmony_ciIn order for that to happen, struct tst_test has a variable called
1707f08c3bdfSopenharmony_ci"restore_wallclock" that should be set to "1" so LTP knows it should: (1)
1708f08c3bdfSopenharmony_ciinitialize a monotonic clock during test setup phase and (2) use that monotonic
1709f08c3bdfSopenharmony_ciclock to fix the system-wide clock time at the test cleanup phase.
1710f08c3bdfSopenharmony_ci
1711f08c3bdfSopenharmony_ci[source,c]
1712f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
1713f08c3bdfSopenharmony_ci#include "tst_test.h"
1714f08c3bdfSopenharmony_ci
1715f08c3bdfSopenharmony_cistatic void setup(void)
1716f08c3bdfSopenharmony_ci{
1717f08c3bdfSopenharmony_ci	...
1718f08c3bdfSopenharmony_ci}
1719f08c3bdfSopenharmony_ci
1720f08c3bdfSopenharmony_cistatic void run(void)
1721f08c3bdfSopenharmony_ci{
1722f08c3bdfSopenharmony_ci	...
1723f08c3bdfSopenharmony_ci}
1724f08c3bdfSopenharmony_ci
1725f08c3bdfSopenharmony_cistruct tst_test test = {
1726f08c3bdfSopenharmony_ci	...
1727f08c3bdfSopenharmony_ci	.setup = setup,
1728f08c3bdfSopenharmony_ci	.test_all = run,
1729f08c3bdfSopenharmony_ci	.restore_wallclock = 1,
1730f08c3bdfSopenharmony_ci	...
1731f08c3bdfSopenharmony_ci};
1732f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
1733f08c3bdfSopenharmony_ci
1734f08c3bdfSopenharmony_ci1.30 Testing similar syscalls in one test
1735f08c3bdfSopenharmony_ci~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1736f08c3bdfSopenharmony_ci
1737f08c3bdfSopenharmony_ciIn some cases kernel has several very similar syscalls that do either the same
1738f08c3bdfSopenharmony_cior very similar job. This is most noticeable on i386 where we commonly have
1739f08c3bdfSopenharmony_citwo or three syscall versions. That is because i386 was first platform that
1740f08c3bdfSopenharmony_ciLinux was developed on and because of that most mistakes in API happened there
1741f08c3bdfSopenharmony_cias well. However this is not limited to i386 at all, it's quite common that
1742f08c3bdfSopenharmony_civersion two syscall has added missing flags parameters or so.
1743f08c3bdfSopenharmony_ci
1744f08c3bdfSopenharmony_ciIn such cases it does not make much sense to copy&paste the test code over and
1745f08c3bdfSopenharmony_ciover, rather than that the test library provides support for test variants.
1746f08c3bdfSopenharmony_ciThe idea behind test variants is simple, we run the test several times each
1747f08c3bdfSopenharmony_citime with different syscall variant.
1748f08c3bdfSopenharmony_ci
1749f08c3bdfSopenharmony_ciThe implementation consist of test_variants integer that, if set, denotes number
1750f08c3bdfSopenharmony_ciof test variants. The test is then forked and executed test_variants times each
1751f08c3bdfSopenharmony_citime with different value in global tst_variant variable.
1752f08c3bdfSopenharmony_ci
1753f08c3bdfSopenharmony_ci[source,c]
1754f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
1755f08c3bdfSopenharmony_ci#include "tst_test.h"
1756f08c3bdfSopenharmony_ci
1757f08c3bdfSopenharmony_cistatic int do_foo(void)
1758f08c3bdfSopenharmony_ci{
1759f08c3bdfSopenharmony_ci	switch (tst_variant) {
1760f08c3bdfSopenharmony_ci	case 0:
1761f08c3bdfSopenharmony_ci		return foo();
1762f08c3bdfSopenharmony_ci	case 1:
1763f08c3bdfSopenharmony_ci		return syscall(__NR_foo);
1764f08c3bdfSopenharmony_ci	}
1765f08c3bdfSopenharmony_ci
1766f08c3bdfSopenharmony_ci	return -1;
1767f08c3bdfSopenharmony_ci}
1768f08c3bdfSopenharmony_ci
1769f08c3bdfSopenharmony_cistatic void run(void)
1770f08c3bdfSopenharmony_ci{
1771f08c3bdfSopenharmony_ci	...
1772f08c3bdfSopenharmony_ci
1773f08c3bdfSopenharmony_ci	TEST(do_foo);
1774f08c3bdfSopenharmony_ci
1775f08c3bdfSopenharmony_ci	...
1776f08c3bdfSopenharmony_ci}
1777f08c3bdfSopenharmony_ci
1778f08c3bdfSopenharmony_cistatic void setup(void)
1779f08c3bdfSopenharmony_ci{
1780f08c3bdfSopenharmony_ci	switch (tst_variant) {
1781f08c3bdfSopenharmony_ci	case 0:
1782f08c3bdfSopenharmony_ci		tst_res(TINFO, "Testing foo variant 1");
1783f08c3bdfSopenharmony_ci	break;
1784f08c3bdfSopenharmony_ci	case 1:
1785f08c3bdfSopenharmony_ci		tst_res(TINFO, "Testing foo variant 2");
1786f08c3bdfSopenharmony_ci	break;
1787f08c3bdfSopenharmony_ci	}
1788f08c3bdfSopenharmony_ci}
1789f08c3bdfSopenharmony_ci
1790f08c3bdfSopenharmony_cistruct tst_test test = {
1791f08c3bdfSopenharmony_ci	...
1792f08c3bdfSopenharmony_ci	.setup = setup,
1793f08c3bdfSopenharmony_ci	.test_all = run,
1794f08c3bdfSopenharmony_ci	.test_variants = 2,
1795f08c3bdfSopenharmony_ci	...
1796f08c3bdfSopenharmony_ci};
1797f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
1798f08c3bdfSopenharmony_ci
1799f08c3bdfSopenharmony_ci1.31 Guarded buffers
1800f08c3bdfSopenharmony_ci~~~~~~~~~~~~~~~~~~~~
1801f08c3bdfSopenharmony_ci
1802f08c3bdfSopenharmony_ciThe test library supports guarded buffers, which are buffers allocated so
1803f08c3bdfSopenharmony_cithat:
1804f08c3bdfSopenharmony_ci
1805f08c3bdfSopenharmony_ci* The end of the buffer is followed by a PROT_NONE page
1806f08c3bdfSopenharmony_ci
1807f08c3bdfSopenharmony_ci* The remainder of the page before the buffer is filled with random canary
1808f08c3bdfSopenharmony_ci  data
1809f08c3bdfSopenharmony_ci
1810f08c3bdfSopenharmony_ciWhich means that the any access after the buffer will yield a Segmentation
1811f08c3bdfSopenharmony_cifault or EFAULT depending on if the access happened in userspace or the kernel
1812f08c3bdfSopenharmony_cirespectively. The canary before the buffer will also catch any write access
1813f08c3bdfSopenharmony_cioutside of the buffer.
1814f08c3bdfSopenharmony_ci
1815f08c3bdfSopenharmony_ciThe purpose of the patch is to catch off-by-one bugs which happens when
1816f08c3bdfSopenharmony_cibuffers and structures are passed to syscalls. New tests should allocate
1817f08c3bdfSopenharmony_ciguarded buffers for all data passed to the tested syscall which are passed by
1818f08c3bdfSopenharmony_cia pointer.
1819f08c3bdfSopenharmony_ci
1820f08c3bdfSopenharmony_ci[source,c]
1821f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
1822f08c3bdfSopenharmony_ci#include "tst_test.h"
1823f08c3bdfSopenharmony_ci
1824f08c3bdfSopenharmony_cistatic struct foo *foo_ptr;
1825f08c3bdfSopenharmony_cistatic struct iovec *iov;
1826f08c3bdfSopenharmony_cistatic void *buf_ptr;
1827f08c3bdfSopenharmony_cistatic char *id;
1828f08c3bdfSopenharmony_ci...
1829f08c3bdfSopenharmony_ci
1830f08c3bdfSopenharmony_cistatic void run(void)
1831f08c3bdfSopenharmony_ci{
1832f08c3bdfSopenharmony_ci	...
1833f08c3bdfSopenharmony_ci
1834f08c3bdfSopenharmony_ci	foo_ptr->bar = 1;
1835f08c3bdfSopenharmony_ci	foo_ptr->buf = buf_ptr;
1836f08c3bdfSopenharmony_ci
1837f08c3bdfSopenharmony_ci	...
1838f08c3bdfSopenharmony_ci}
1839f08c3bdfSopenharmony_ci
1840f08c3bdfSopenharmony_cistatic void setup(void)
1841f08c3bdfSopenharmony_ci{
1842f08c3bdfSopenharmony_ci	...
1843f08c3bdfSopenharmony_ci
1844f08c3bdfSopenharmony_ci	id = tst_strdup(string);
1845f08c3bdfSopenharmony_ci
1846f08c3bdfSopenharmony_ci	...
1847f08c3bdfSopenharmony_ci}
1848f08c3bdfSopenharmony_ci
1849f08c3bdfSopenharmony_cistatic struct tst_test test = {
1850f08c3bdfSopenharmony_ci	...
1851f08c3bdfSopenharmony_ci	.bufs = (struct tst_buffers []) {
1852f08c3bdfSopenharmony_ci		{&foo_ptr, .size = sizeof(*foo_ptr)},
1853f08c3bdfSopenharmony_ci		{&buf_ptr, .size = BUF_SIZE},
1854f08c3bdfSopenharmony_ci		{&iov, .iov_sizes = (int[]){128, 32, -1},
1855f08c3bdfSopenharmony_ci		{}
1856f08c3bdfSopenharmony_ci	}
1857f08c3bdfSopenharmony_ci};
1858f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
1859f08c3bdfSopenharmony_ci
1860f08c3bdfSopenharmony_ciGuarded buffers can be allocated on runtime in a test setup() by a
1861f08c3bdfSopenharmony_ci'tst_alloc()' or by 'tst_strdup()' as well as by filling up the .bufs array in
1862f08c3bdfSopenharmony_cithe tst_test structure.
1863f08c3bdfSopenharmony_ci
1864f08c3bdfSopenharmony_ciSo far the tst_test structure supports allocating either a plain buffer by
1865f08c3bdfSopenharmony_cisetting up the size or struct iovec, which is allocated recursively including
1866f08c3bdfSopenharmony_cithe individual buffers as described by an '-1' terminated array of buffer
1867f08c3bdfSopenharmony_cisizes.
1868f08c3bdfSopenharmony_ci
1869f08c3bdfSopenharmony_ci1.32 Adding and removing capabilities
1870f08c3bdfSopenharmony_ci~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1871f08c3bdfSopenharmony_ci
1872f08c3bdfSopenharmony_ciSome tests may require the presence or absence of particular
1873f08c3bdfSopenharmony_cicapabilities. Using the API provided by 'tst_capability.h' the test author can
1874f08c3bdfSopenharmony_citry to ensure that some capabilities are either present or absent during the
1875f08c3bdfSopenharmony_citest.
1876f08c3bdfSopenharmony_ci
1877f08c3bdfSopenharmony_ciFor example; below we try to create a raw socket, which requires
1878f08c3bdfSopenharmony_ciCAP_NET_ADMIN. During setup we should be able to do it, then during run it
1879f08c3bdfSopenharmony_cishould be impossible. The LTP capability library will check before setup that
1880f08c3bdfSopenharmony_ciwe have this capability, then after setup it will drop it.
1881f08c3bdfSopenharmony_ci
1882f08c3bdfSopenharmony_ci[source,c]
1883f08c3bdfSopenharmony_ci--------------------------------------------------------------------------------
1884f08c3bdfSopenharmony_ci#include "tst_test.h"
1885f08c3bdfSopenharmony_ci#include "tst_capability.h"
1886f08c3bdfSopenharmony_ci#include "tst_safe_net.h"
1887f08c3bdfSopenharmony_ci
1888f08c3bdfSopenharmony_ci#include "lapi/socket.h"
1889f08c3bdfSopenharmony_ci
1890f08c3bdfSopenharmony_cistatic void run(void)
1891f08c3bdfSopenharmony_ci{
1892f08c3bdfSopenharmony_ci	TEST(socket(AF_INET, SOCK_RAW, 1));
1893f08c3bdfSopenharmony_ci	if (TST_RET > -1) {
1894f08c3bdfSopenharmony_ci		tst_res(TFAIL, "Created raw socket");
1895f08c3bdfSopenharmony_ci	} else if (TST_ERR != EPERM) {
1896f08c3bdfSopenharmony_ci		tst_res(TFAIL | TTERRNO,
1897f08c3bdfSopenharmony_ci			"Failed to create socket for wrong reason");
1898f08c3bdfSopenharmony_ci	} else {
1899f08c3bdfSopenharmony_ci		tst_res(TPASS | TTERRNO, "Didn't create raw socket");
1900f08c3bdfSopenharmony_ci	}
1901f08c3bdfSopenharmony_ci}
1902f08c3bdfSopenharmony_ci
1903f08c3bdfSopenharmony_cistatic void setup(void)
1904f08c3bdfSopenharmony_ci{
1905f08c3bdfSopenharmony_ci	TEST(socket(AF_INET, SOCK_RAW, 1));
1906f08c3bdfSopenharmony_ci	if (TST_RET < 0)
1907f08c3bdfSopenharmony_ci		tst_brk(TCONF | TTERRNO, "We don't have CAP_NET_RAW to begin with");
1908f08c3bdfSopenharmony_ci
1909f08c3bdfSopenharmony_ci	SAFE_CLOSE(TST_RET);
1910f08c3bdfSopenharmony_ci}
1911f08c3bdfSopenharmony_ci
1912f08c3bdfSopenharmony_cistatic struct tst_test test = {
1913f08c3bdfSopenharmony_ci	.setup = setup,
1914f08c3bdfSopenharmony_ci	.test_all = run,
1915f08c3bdfSopenharmony_ci	.caps = (struct tst_cap []) {
1916f08c3bdfSopenharmony_ci		TST_CAP(TST_CAP_REQ, CAP_NET_RAW),
1917f08c3bdfSopenharmony_ci		TST_CAP(TST_CAP_DROP, CAP_NET_RAW),
1918f08c3bdfSopenharmony_ci		{}
1919f08c3bdfSopenharmony_ci	},
1920f08c3bdfSopenharmony_ci};
1921f08c3bdfSopenharmony_ci--------------------------------------------------------------------------------
1922f08c3bdfSopenharmony_ci
1923f08c3bdfSopenharmony_ciLook at the test struct at the bottom. We have filled in the 'caps' field with
1924f08c3bdfSopenharmony_cia 'NULL' terminated array containing two 'tst_cap' structs. 'TST_CAP_REQ'
1925f08c3bdfSopenharmony_ciactions are executed before setup and 'TST_CAP_DROP' are executed after
1926f08c3bdfSopenharmony_cisetup. This means it is possible to both request and drop a capability.
1927f08c3bdfSopenharmony_ci
1928f08c3bdfSopenharmony_ci[source,c]
1929f08c3bdfSopenharmony_ci--------------------------------------------------------------------------------
1930f08c3bdfSopenharmony_cistatic struct tst_test test = {
1931f08c3bdfSopenharmony_ci	.test_all = run,
1932f08c3bdfSopenharmony_ci	.caps = (struct tst_cap []) {
1933f08c3bdfSopenharmony_ci		TST_CAP(TST_CAP_REQ, CAP_NET_RAW),
1934f08c3bdfSopenharmony_ci		TST_CAP(TST_CAP_DROP, CAP_SYS_ADMIN),
1935f08c3bdfSopenharmony_ci		{}
1936f08c3bdfSopenharmony_ci	},
1937f08c3bdfSopenharmony_ci};
1938f08c3bdfSopenharmony_ci--------------------------------------------------------------------------------
1939f08c3bdfSopenharmony_ci
1940f08c3bdfSopenharmony_ciHere we request 'CAP_NET_RAW', but drop 'CAP_SYS_ADMIN'. If the capability is
1941f08c3bdfSopenharmony_ciin the permitted set, but not the effective set, the library will try to
1942f08c3bdfSopenharmony_cipermit it. If it is not in the permitted set, then it will fail with 'TCONF'.
1943f08c3bdfSopenharmony_ci
1944f08c3bdfSopenharmony_ciThis API does not require 'libcap' to be installed. However it has limited
1945f08c3bdfSopenharmony_cifeatures relative to 'libcap'. It only tries to add or remove capabilities
1946f08c3bdfSopenharmony_cifrom the effective set. This means that tests which need to spawn child
1947f08c3bdfSopenharmony_ciprocesses may have difficulties ensuring the correct capabilities are
1948f08c3bdfSopenharmony_ciavailable to the children (see the capabilities (7) manual pages).
1949f08c3bdfSopenharmony_ci
1950f08c3bdfSopenharmony_ciHowever a lot of problems can be solved by using 'tst_cap_action(struct
1951f08c3bdfSopenharmony_citst_cap  *cap)' directly which can be called at any time. This also helps if
1952f08c3bdfSopenharmony_ciyou wish to drop a capability at the beginning of setup.
1953f08c3bdfSopenharmony_ci
1954f08c3bdfSopenharmony_ci1.33 Reproducing race-conditions
1955f08c3bdfSopenharmony_ci~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1956f08c3bdfSopenharmony_ci
1957f08c3bdfSopenharmony_ciIf a bug is caused by two tasks in the kernel racing and you wish to create a
1958f08c3bdfSopenharmony_ciregression test (or bug-fix validation test) then the 'tst_fuzzy_sync.h'
1959f08c3bdfSopenharmony_cilibrary should be used.
1960f08c3bdfSopenharmony_ci
1961f08c3bdfSopenharmony_ciIt allows you to specify, in your code, two race windows. One window in each
1962f08c3bdfSopenharmony_cithread's loop (triggering a race usually requires many iterations). These
1963f08c3bdfSopenharmony_ciwindows show fuzzy-sync where the race can happen. They don't need to be
1964f08c3bdfSopenharmony_ciexact, hence the 'fuzzy' part. If the race condition is not immediately
1965f08c3bdfSopenharmony_citriggered then the library will begin experimenting with different timings.
1966f08c3bdfSopenharmony_ci
1967f08c3bdfSopenharmony_ci[source,c]
1968f08c3bdfSopenharmony_ci--------------------------------------------------------------------------------
1969f08c3bdfSopenharmony_ci#include "tst_fuzzy_sync.h"
1970f08c3bdfSopenharmony_ci
1971f08c3bdfSopenharmony_cistatic struct tst_fzsync_pair fzsync_pair;
1972f08c3bdfSopenharmony_ci
1973f08c3bdfSopenharmony_cistatic void setup(void)
1974f08c3bdfSopenharmony_ci{
1975f08c3bdfSopenharmony_ci        tst_fzsync_pair_init(&fzsync_pair);
1976f08c3bdfSopenharmony_ci}
1977f08c3bdfSopenharmony_ci
1978f08c3bdfSopenharmony_cistatic void cleanup(void)
1979f08c3bdfSopenharmony_ci{
1980f08c3bdfSopenharmony_ci	tst_fzsync_pair_cleanup(&fzsync_pair);
1981f08c3bdfSopenharmony_ci}
1982f08c3bdfSopenharmony_ci
1983f08c3bdfSopenharmony_cistatic void *thread_b(void *arg)
1984f08c3bdfSopenharmony_ci{
1985f08c3bdfSopenharmony_ci	while (tst_fzsync_run_b(&fzsync_pair)) {
1986f08c3bdfSopenharmony_ci
1987f08c3bdfSopenharmony_ci		tst_fzsync_start_race_b(&fzsync_pair);
1988f08c3bdfSopenharmony_ci
1989f08c3bdfSopenharmony_ci                /* This is the race window for thread B */
1990f08c3bdfSopenharmony_ci
1991f08c3bdfSopenharmony_ci                tst_fzsync_end_race_b(&fzsync_pair);
1992f08c3bdfSopenharmony_ci	}
1993f08c3bdfSopenharmony_ci
1994f08c3bdfSopenharmony_ci	return arg;
1995f08c3bdfSopenharmony_ci}
1996f08c3bdfSopenharmony_ci
1997f08c3bdfSopenharmony_cistatic void thread_a(void)
1998f08c3bdfSopenharmony_ci{
1999f08c3bdfSopenharmony_ci	tst_fzsync_pair_reset(&fzsync_pair, thread_b);
2000f08c3bdfSopenharmony_ci
2001f08c3bdfSopenharmony_ci        while (tst_fzsync_run_a(&fzsync_pair)) {
2002f08c3bdfSopenharmony_ci
2003f08c3bdfSopenharmony_ci		tst_fzsync_start_race_a(&fzsync_pair);
2004f08c3bdfSopenharmony_ci
2005f08c3bdfSopenharmony_ci		/* This is the race window for thread A */
2006f08c3bdfSopenharmony_ci
2007f08c3bdfSopenharmony_ci                tst_fzsync_end_race_a(&fzsync_pair);
2008f08c3bdfSopenharmony_ci	}
2009f08c3bdfSopenharmony_ci}
2010f08c3bdfSopenharmony_ci
2011f08c3bdfSopenharmony_cistatic struct tst_test test = {
2012f08c3bdfSopenharmony_ci	.test_all = thread_a,
2013f08c3bdfSopenharmony_ci	.setup = setup,
2014f08c3bdfSopenharmony_ci	.cleanup = cleanup,
2015f08c3bdfSopenharmony_ci};
2016f08c3bdfSopenharmony_ci--------------------------------------------------------------------------------
2017f08c3bdfSopenharmony_ci
2018f08c3bdfSopenharmony_ciAbove is a minimal template for a test using fuzzy-sync. In a simple case, you
2019f08c3bdfSopenharmony_cijust need to put the bits you want to race inbetween 'start_race' and
2020f08c3bdfSopenharmony_ci'end_race'. Meanwhile, any setup you need to do per-iteration goes outside the
2021f08c3bdfSopenharmony_ciwindows.
2022f08c3bdfSopenharmony_ci
2023f08c3bdfSopenharmony_ciFuzzy sync synchronises 'run_a' and 'run_b', which act as barriers, so that
2024f08c3bdfSopenharmony_cineither thread can progress until the other has caught up with it. There is
2025f08c3bdfSopenharmony_cialso the 'pair_wait' function which can be used to add barriers in other
2026f08c3bdfSopenharmony_cilocations. Of course 'start/end_race_a/b' are also a barriers.
2027f08c3bdfSopenharmony_ci
2028f08c3bdfSopenharmony_ciThe library decides how long the test should run for based on the timeout
2029f08c3bdfSopenharmony_cispecified by the user plus some other heuristics.
2030f08c3bdfSopenharmony_ci
2031f08c3bdfSopenharmony_ciFor full documentation see the comments in 'include/tst_fuzzy_sync.h'.
2032f08c3bdfSopenharmony_ci
2033f08c3bdfSopenharmony_ci1.34 Reserving hugepages
2034f08c3bdfSopenharmony_ci~~~~~~~~~~~~~~~~~~~~~~~~
2035f08c3bdfSopenharmony_ci
2036f08c3bdfSopenharmony_ciMany of the LTP tests need to use hugepage in their testing, this allows the
2037f08c3bdfSopenharmony_citest can reserve hugepages from system via '.hugepages = {xx, TST_REQUEST}'.
2038f08c3bdfSopenharmony_ci
2039f08c3bdfSopenharmony_ciWe achieved two policies for reserving hugepages:
2040f08c3bdfSopenharmony_ci
2041f08c3bdfSopenharmony_ciTST_REQUEST:
2042f08c3bdfSopenharmony_ci  It will try the best to reserve available huge pages and return the number
2043f08c3bdfSopenharmony_ci  of available hugepages in tst_hugepages, which may be 0 if hugepages are
2044f08c3bdfSopenharmony_ci  not supported at all.
2045f08c3bdfSopenharmony_ci
2046f08c3bdfSopenharmony_ciTST_NEEDS:
2047f08c3bdfSopenharmony_ci  This is an enforced requirement, LTP should strictly do hpages applying and
2048f08c3bdfSopenharmony_ci  guarantee the 'HugePages_Free' no less than pages which makes that test can
2049f08c3bdfSopenharmony_ci  use these specified numbers correctly. Otherwise, test exits with TCONF if
2050f08c3bdfSopenharmony_ci  the attempt to reserve hugepages fails or reserves less than requested.
2051f08c3bdfSopenharmony_ci
2052f08c3bdfSopenharmony_ciWith success test stores the reserved hugepage number in 'tst_hugepages'. For
2053f08c3bdfSopenharmony_cisystem without hugetlb supporting, variable 'tst_hugepages' will be set to 0.
2054f08c3bdfSopenharmony_ciIf the hugepage number needs to be set to 0 on supported hugetlb system, please
2055f08c3bdfSopenharmony_ciuse '.hugepages = {TST_NO_HUGEPAGES}'.
2056f08c3bdfSopenharmony_ci
2057f08c3bdfSopenharmony_ciAlso, we do cleanup and restore work for the hpages resetting automatically.
2058f08c3bdfSopenharmony_ci
2059f08c3bdfSopenharmony_ci[source,c]
2060f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
2061f08c3bdfSopenharmony_ci#include "tst_test.h"
2062f08c3bdfSopenharmony_ci
2063f08c3bdfSopenharmony_cistatic void run(void)
2064f08c3bdfSopenharmony_ci{
2065f08c3bdfSopenharmony_ci	...
2066f08c3bdfSopenharmony_ci
2067f08c3bdfSopenharmony_ci	if (tst_hugepages == test.hugepages.number)
2068f08c3bdfSopenharmony_ci		TEST(do_hpage_test);
2069f08c3bdfSopenharmony_ci	else
2070f08c3bdfSopenharmony_ci		...
2071f08c3bdfSopenharmony_ci	...
2072f08c3bdfSopenharmony_ci}
2073f08c3bdfSopenharmony_ci
2074f08c3bdfSopenharmony_cistruct tst_test test = {
2075f08c3bdfSopenharmony_ci	.test_all = run,
2076f08c3bdfSopenharmony_ci	.hugepages = {2, TST_REQUEST},
2077f08c3bdfSopenharmony_ci	...
2078f08c3bdfSopenharmony_ci};
2079f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
2080f08c3bdfSopenharmony_ci
2081f08c3bdfSopenharmony_cior,
2082f08c3bdfSopenharmony_ci
2083f08c3bdfSopenharmony_ci[source,c]
2084f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
2085f08c3bdfSopenharmony_ci#include "tst_test.h"
2086f08c3bdfSopenharmony_ci
2087f08c3bdfSopenharmony_cistatic void run(void)
2088f08c3bdfSopenharmony_ci{
2089f08c3bdfSopenharmony_ci	...
2090f08c3bdfSopenharmony_ci}
2091f08c3bdfSopenharmony_ci
2092f08c3bdfSopenharmony_cistatic void setup(void)
2093f08c3bdfSopenharmony_ci{
2094f08c3bdfSopenharmony_ci	/* TST_NEEDS achieved this automatically in the library */
2095f08c3bdfSopenharmony_ci	if (tst_hugepages != test.hugepages.number)
2096f08c3bdfSopenharmony_ci		tst_brk(TCONF, "...");
2097f08c3bdfSopenharmony_ci}
2098f08c3bdfSopenharmony_ci
2099f08c3bdfSopenharmony_cistruct tst_test test = {
2100f08c3bdfSopenharmony_ci	.test_all = run,
2101f08c3bdfSopenharmony_ci	.hugepages = {2, TST_NEEDS},
2102f08c3bdfSopenharmony_ci	...
2103f08c3bdfSopenharmony_ci};
2104f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
2105f08c3bdfSopenharmony_ci
2106f08c3bdfSopenharmony_ci1.35 Checking for required commands
2107f08c3bdfSopenharmony_ci~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2108f08c3bdfSopenharmony_ci
2109f08c3bdfSopenharmony_ciRequired commands can be checked with '.needs_cmds', which points to a 'NULL'
2110f08c3bdfSopenharmony_citerminated array of strings such as:
2111f08c3bdfSopenharmony_ci
2112f08c3bdfSopenharmony_ci[source,c]
2113f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
2114f08c3bdfSopenharmony_ci.needs_cmds = (const char *const []) {
2115f08c3bdfSopenharmony_ci	"useradd",
2116f08c3bdfSopenharmony_ci	"userdel",
2117f08c3bdfSopenharmony_ci	NULL
2118f08c3bdfSopenharmony_ci},
2119f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
2120f08c3bdfSopenharmony_ci
2121f08c3bdfSopenharmony_ciAlso can check required command version whether is satisfied by using 'needs_cmds'
2122f08c3bdfSopenharmony_cisuch as:
2123f08c3bdfSopenharmony_ci
2124f08c3bdfSopenharmony_ci[source,c]
2125f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
2126f08c3bdfSopenharmony_ci.needs_cmds = (const char *const []) {
2127f08c3bdfSopenharmony_ci	"mkfs.ext4 >= 1.43.0",
2128f08c3bdfSopenharmony_ci	NULL
2129f08c3bdfSopenharmony_ci},
2130f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
2131f08c3bdfSopenharmony_ci
2132f08c3bdfSopenharmony_ciCurrently, we only support mkfs.ext4 command version check.
2133f08c3bdfSopenharmony_ciIf you want to support more commands, please fill your own .parser and .table_get
2134f08c3bdfSopenharmony_cimethod in the version_parsers structure of lib/tst_cmd.c.
2135f08c3bdfSopenharmony_ci
2136f08c3bdfSopenharmony_ci1.36 Assert sys or proc file value
2137f08c3bdfSopenharmony_ci~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2138f08c3bdfSopenharmony_ciUsing TST_ASSERT_INT/STR(path, val) to assert that integer value or string stored in
2139f08c3bdfSopenharmony_cithe prefix field of file pointed by path equals to the value passed to this function.
2140f08c3bdfSopenharmony_ci
2141f08c3bdfSopenharmony_ciAlso having a similar api pair TST_ASSERT_FILE_INT/STR(path, prefix, val) to assert
2142f08c3bdfSopenharmony_cithe field value of file.
2143f08c3bdfSopenharmony_ci
2144f08c3bdfSopenharmony_ci1.37 Using Control Group
2145f08c3bdfSopenharmony_ci~~~~~~~~~~~~~~~~~~~~~~~~
2146f08c3bdfSopenharmony_ci
2147f08c3bdfSopenharmony_ciSome LTP tests need specific Control Group configurations.  'tst_cgroup.h'
2148f08c3bdfSopenharmony_ciprovides APIs to discover and use CGroups. There are many differences between
2149f08c3bdfSopenharmony_ciCGroups API V1 and V2. We encapsulate the details of configuring CGroups in
2150f08c3bdfSopenharmony_cihigh-level functions which follow the V2 kernel API where possible. Allowing one
2151f08c3bdfSopenharmony_cito write code that works on both V1 or V2. At least some of the time anyway;
2152f08c3bdfSopenharmony_cioften the behavioural differences between V1 and V2 are too great. In such cases
2153f08c3bdfSopenharmony_ciwe revert to branching on the CGroup version.
2154f08c3bdfSopenharmony_ci
2155f08c3bdfSopenharmony_ciAlso, the LTP library will automatically mount/umount and configure the CGroup
2156f08c3bdfSopenharmony_cihierarchies if that is required (e.g. if you run the tests from init with no
2157f08c3bdfSopenharmony_cisystem manager).
2158f08c3bdfSopenharmony_ci
2159f08c3bdfSopenharmony_ci[source,c]
2160f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
2161f08c3bdfSopenharmony_ci#include "tst_test.h"
2162f08c3bdfSopenharmony_ci
2163f08c3bdfSopenharmony_cistatic void run(void)
2164f08c3bdfSopenharmony_ci{
2165f08c3bdfSopenharmony_ci	...
2166f08c3bdfSopenharmony_ci	// do test under cgroup
2167f08c3bdfSopenharmony_ci	...
2168f08c3bdfSopenharmony_ci}
2169f08c3bdfSopenharmony_ci
2170f08c3bdfSopenharmony_cistatic void setup(void)
2171f08c3bdfSopenharmony_ci{
2172f08c3bdfSopenharmony_ci	SAFE_CG_PRINTF(tst_cg, "cgroup.procs", "%d", getpid());
2173f08c3bdfSopenharmony_ci	SAFE_CG_PRINTF(tst_cg, "memory.max", "%lu", MEMSIZE);
2174f08c3bdfSopenharmony_ci	if (SAFE_CG_HAS(tst_cg, "memory.swap.max"))
2175f08c3bdfSopenharmony_ci		SAFE_CG_PRINTF(tst_cg, "memory.swap.max", "%zu", memsw);
2176f08c3bdfSopenharmony_ci}
2177f08c3bdfSopenharmony_ci
2178f08c3bdfSopenharmony_cistruct tst_test test = {
2179f08c3bdfSopenharmony_ci	.setup = setup,
2180f08c3bdfSopenharmony_ci	.test_all = run,
2181f08c3bdfSopenharmony_ci	.cleanup = cleanup,
2182f08c3bdfSopenharmony_ci	.needs_cgroup_ctrls = (const char *const []){ "memory", NULL },
2183f08c3bdfSopenharmony_ci	...
2184f08c3bdfSopenharmony_ci};
2185f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
2186f08c3bdfSopenharmony_ci
2187f08c3bdfSopenharmony_ciAbove, we first ensure the memory controller is available on the
2188f08c3bdfSopenharmony_citest's CGroup with '.needs_cgroup_ctrls'. This populates a structure,
2189f08c3bdfSopenharmony_ci'tst_cg', which represents the test's CGroup.
2190f08c3bdfSopenharmony_ci
2191f08c3bdfSopenharmony_ciWe then write the current processes PID into 'cgroup.procs', which
2192f08c3bdfSopenharmony_cimoves the current process into the test's CGroup. After which we set
2193f08c3bdfSopenharmony_cithe maximum memory size by writing to 'memory.max'. If the memory
2194f08c3bdfSopenharmony_cicontroller is mounted on CGroups V1 then the library will actually
2195f08c3bdfSopenharmony_ciwrite to 'memory.limit_in_bytes'. As a general rule, if a file exists
2196f08c3bdfSopenharmony_cion both CGroup versions, then we use the V2 naming.
2197f08c3bdfSopenharmony_ci
2198f08c3bdfSopenharmony_ciSome controller features, such as 'memory.swap', can be
2199f08c3bdfSopenharmony_cidisabled. Therefor we need to check if they exist before accessing
2200f08c3bdfSopenharmony_cithem. This can be done with 'SAFE_CG_HAS' which can be called on
2201f08c3bdfSopenharmony_ciany control file or feature.
2202f08c3bdfSopenharmony_ci
2203f08c3bdfSopenharmony_ciMost tests only require setting a few limits similar to the above. In
2204f08c3bdfSopenharmony_cisuch cases the differences between V1 and V2 are hidden. Setup and
2205f08c3bdfSopenharmony_cicleanup is also mostly hidden. However things can get much worse.
2206f08c3bdfSopenharmony_ci
2207f08c3bdfSopenharmony_ci[source,c]
2208f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
2209f08c3bdfSopenharmony_cistatic struct tst_cg_group *cg_child;
2210f08c3bdfSopenharmony_ci
2211f08c3bdfSopenharmony_cistatic void run(void)
2212f08c3bdfSopenharmony_ci{
2213f08c3bdfSopenharmony_ci	char buf[BUFSIZ];
2214f08c3bdfSopenharmony_ci	size_t mem = 0;
2215f08c3bdfSopenharmony_ci
2216f08c3bdfSopenharmony_ci	cg_child = tst_cg_group_mk(tst_cg, "child");
2217f08c3bdfSopenharmony_ci	SAFE_CG_PRINTF(cg_child, "cgroup.procs", "%d", getpid());
2218f08c3bdfSopenharmony_ci
2219f08c3bdfSopenharmony_ci	if (!TST_CG_VER_IS_V1(tst_cg, "memory"))
2220f08c3bdfSopenharmony_ci		SAFE_CG_PRINT(tst_cg, "cgroup.subtree_control", "+memory");
2221f08c3bdfSopenharmony_ci	if (!TST_CG_VER_IS_V1(tst_cg, "cpuset"))
2222f08c3bdfSopenharmony_ci		SAFE_CG_PRINT(tst_cg, "cgroup.subtree_control", "+cpuset");
2223f08c3bdfSopenharmony_ci
2224f08c3bdfSopenharmony_ci	if (!SAFE_FORK()) {
2225f08c3bdfSopenharmony_ci		SAFE_CG_PRINTF(cg_child, "cgroup.procs", "%d", getpid());
2226f08c3bdfSopenharmony_ci
2227f08c3bdfSopenharmony_ci		if (SAFE_CG_HAS(cg_child, "memory.swap")) {
2228f08c3bdfSopenharmony_ci			SAFE_CG_SCANF(cg_child,
2229f08c3bdfSopenharmony_ci					  "memory.swap.current", "%zu", &mem);
2230f08c3bdfSopenharmony_ci		}
2231f08c3bdfSopenharmony_ci		SAFE_CG_READ(cg_child, "cpuset.mems", buf, sizeof(buf));
2232f08c3bdfSopenharmony_ci
2233f08c3bdfSopenharmony_ci		// Do something with cpuset.mems and memory.current values
2234f08c3bdfSopenharmony_ci		...
2235f08c3bdfSopenharmony_ci
2236f08c3bdfSopenharmony_ci		exit(0);
2237f08c3bdfSopenharmony_ci	}
2238f08c3bdfSopenharmony_ci
2239f08c3bdfSopenharmony_ci	tst_reap_children();
2240f08c3bdfSopenharmony_ci	SAFE_CG_PRINTF(tst_cg_drain, "cgroup.procs", "%d", getpid());
2241f08c3bdfSopenharmony_ci	cg_child = tst_cg_group_rm(cg_child);
2242f08c3bdfSopenharmony_ci}
2243f08c3bdfSopenharmony_ci
2244f08c3bdfSopenharmony_cistatic void cleanup(void)
2245f08c3bdfSopenharmony_ci{
2246f08c3bdfSopenharmony_ci	if (cg_child) {
2247f08c3bdfSopenharmony_ci		SAFE_CG_PRINTF(tst_cg_drain, "cgroup.procs", "%d", getpid());
2248f08c3bdfSopenharmony_ci		cg_child = tst_cg_group_rm(cg_child);
2249f08c3bdfSopenharmony_ci	}
2250f08c3bdfSopenharmony_ci}
2251f08c3bdfSopenharmony_ci
2252f08c3bdfSopenharmony_cistruct tst_test test = {
2253f08c3bdfSopenharmony_ci	.setup = setup,
2254f08c3bdfSopenharmony_ci	.test_all = run,
2255f08c3bdfSopenharmony_ci	.needs_cgroup_ctrls = (const char *const []){
2256f08c3bdfSopenharmony_ci		"cpuset",
2257f08c3bdfSopenharmony_ci		"memory",
2258f08c3bdfSopenharmony_ci		NULL
2259f08c3bdfSopenharmony_ci	},
2260f08c3bdfSopenharmony_ci	...
2261f08c3bdfSopenharmony_ci};
2262f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
2263f08c3bdfSopenharmony_ci
2264f08c3bdfSopenharmony_ciStarting with setup; we can see here that we fetch the 'drain'
2265f08c3bdfSopenharmony_ciCGroup. This is a shared group (between parallel tests) which may
2266f08c3bdfSopenharmony_cicontain processes from other tests. It should have default settings
2267f08c3bdfSopenharmony_ciand these should not be changed by the test. It can be used to remove
2268f08c3bdfSopenharmony_ciprocesses from other CGroups incase the hierarchy root is not
2269f08c3bdfSopenharmony_ciaccessible.
2270f08c3bdfSopenharmony_ci
2271f08c3bdfSopenharmony_ciNote that 'tst_cg_get_drain_group' should not be called many times,
2272f08c3bdfSopenharmony_cias it is allocated in a guarded buffer (See section 2.2.31). Therefor
2273f08c3bdfSopenharmony_ciit is best to call it once in 'setup' and not 'run' because 'run' may
2274f08c3bdfSopenharmony_cibe repeated with the '-i' option.
2275f08c3bdfSopenharmony_ci
2276f08c3bdfSopenharmony_ciIn 'run', we first create a child CGroup with 'tst_cg_mk'. As we
2277f08c3bdfSopenharmony_cicreate this CGroup in 'run' we should also remove it at the end of
2278f08c3bdfSopenharmony_cirun. We also need to check if it exists and remove it in cleanup as
2279f08c3bdfSopenharmony_ciwell. Because there are 'SAFE_' functions which may jump to cleanup.
2280f08c3bdfSopenharmony_ci
2281f08c3bdfSopenharmony_ciWe then move the main test process into the child CGroup. This is
2282f08c3bdfSopenharmony_ciimportant as it means that before we destroy the child CGroup we have
2283f08c3bdfSopenharmony_cito move the main test process elsewhere. For that we use the 'drain'
2284f08c3bdfSopenharmony_cigroup.
2285f08c3bdfSopenharmony_ci
2286f08c3bdfSopenharmony_ciNext we enable the memory and cpuset controller configuration on the
2287f08c3bdfSopenharmony_citest CGroup's descendants (i.e. 'cg_child'). This allows each child to
2288f08c3bdfSopenharmony_cihave its own settings. The file 'cgroup.subtree_control' does not
2289f08c3bdfSopenharmony_ciexist on V1. Because it is possible to have both V1 and V2 active at
2290f08c3bdfSopenharmony_cithe same time. We can not simply check if 'subtree_control' exists
2291f08c3bdfSopenharmony_cibefore writing to it. We have to check if a particular controller is
2292f08c3bdfSopenharmony_cion V2 before trying to add it to 'subtree_control'. Trying to add a V1
2293f08c3bdfSopenharmony_cicontroller will result in 'ENOENT'.
2294f08c3bdfSopenharmony_ci
2295f08c3bdfSopenharmony_ciWe then fork a child process and add this to the child CGroup. Within
2296f08c3bdfSopenharmony_cithe child process we try to read 'memory.swap.current'. It is possible
2297f08c3bdfSopenharmony_cithat the memory controller was compiled without swap support, so it is
2298f08c3bdfSopenharmony_cinecessary to check if 'memory.swap' is enabled. That is unless the
2299f08c3bdfSopenharmony_citest will never reach the point where 'memory.swap.*' are used without
2300f08c3bdfSopenharmony_ciswap support.
2301f08c3bdfSopenharmony_ci
2302f08c3bdfSopenharmony_ciThe parent process waits for the child process to be reaped before
2303f08c3bdfSopenharmony_cidestroying the child CGroup. So there is no need to transfer the child
2304f08c3bdfSopenharmony_cito drain. However the parent process must be moved otherwise we will
2305f08c3bdfSopenharmony_ciget 'EBUSY' when trying to remove the child CGroup.
2306f08c3bdfSopenharmony_ci
2307f08c3bdfSopenharmony_ciAnother example of a behavioral difference between versions is shown below.
2308f08c3bdfSopenharmony_ci
2309f08c3bdfSopenharmony_ci[source,c]
2310f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
2311f08c3bdfSopenharmony_ci	if (TST_CG_VER_IS_V1(tst_cg, "memory"))
2312f08c3bdfSopenharmony_ci		SAFE_CG_PRINTF(tst_cg, "memory.swap.max", "%lu", ~0UL);
2313f08c3bdfSopenharmony_ci	else
2314f08c3bdfSopenharmony_ci		SAFE_CG_PRINT(tst_cg, "memory.swap.max", "max");
2315f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
2316f08c3bdfSopenharmony_ci
2317f08c3bdfSopenharmony_ciCGroups V2 introduced a feature where 'memory[.swap].max' could be set to
2318f08c3bdfSopenharmony_ci"max". This does not appear to work on V1 'limit_in_bytes' however. For most
2319f08c3bdfSopenharmony_citests, simply using a large number is sufficient and there is no need to use
2320f08c3bdfSopenharmony_ci"max". Importantly though, one should be careful to read both the V1 and V2
2321f08c3bdfSopenharmony_cikernel docs. Presently the LTP library does not attempt to handle most
2322f08c3bdfSopenharmony_cidifferences in semantics. It does the minimal amount of work to make testing on
2323f08c3bdfSopenharmony_ciboth V1 and V2 feasible.
2324f08c3bdfSopenharmony_ci
2325f08c3bdfSopenharmony_ci1.38 Require minimum numbers of CPU for a testcase
2326f08c3bdfSopenharmony_ci~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2327f08c3bdfSopenharmony_ci
2328f08c3bdfSopenharmony_ciSome tests require more than specific number of CPU. It can be defined with
2329f08c3bdfSopenharmony_ci`.min_cpus = N`.
2330f08c3bdfSopenharmony_ci
2331f08c3bdfSopenharmony_ci1.39 Require minimum memory or swap size for a testcase
2332f08c3bdfSopenharmony_ci~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2333f08c3bdfSopenharmony_ci
2334f08c3bdfSopenharmony_ciSome tests require at least size(MB) of free RAM or Swap.
2335f08c3bdfSopenharmony_ci
2336f08c3bdfSopenharmony_ciTo make sure that test will run only on systems with more than minimal
2337f08c3bdfSopenharmony_cirequired amount of RAM set `.min_mem_avail = N`.
2338f08c3bdfSopenharmony_ci
2339f08c3bdfSopenharmony_ciSimilarily for tests that require certain amount of free Swap use
2340f08c3bdfSopenharmony_ci`.min_swap_avail = N`.
2341f08c3bdfSopenharmony_ci
2342f08c3bdfSopenharmony_ci1.40 Test tags
2343f08c3bdfSopenharmony_ci~~~~~~~~~~~~~~
2344f08c3bdfSopenharmony_ci
2345f08c3bdfSopenharmony_ciTest tags are name-value pairs that can hold any test metadata.
2346f08c3bdfSopenharmony_ci
2347f08c3bdfSopenharmony_ciWe have additional support for CVE entries, git commit in mainline kernel,
2348f08c3bdfSopenharmony_cistable kernel or glibc git repository.  If a test is a regression test it
2349f08c3bdfSopenharmony_cishould include these tags.  They are printed when test fails and exported
2350f08c3bdfSopenharmony_ciinto documentation.
2351f08c3bdfSopenharmony_ci
2352f08c3bdfSopenharmony_ciCVE, mainline and stable kernel git commits in a regression test for a kernel bug:
2353f08c3bdfSopenharmony_ci[source,c]
2354f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
2355f08c3bdfSopenharmony_cistruct tst_test test = {
2356f08c3bdfSopenharmony_ci	...
2357f08c3bdfSopenharmony_ci	.tags = (const struct tst_tag[]) {
2358f08c3bdfSopenharmony_ci		{"linux-git", "9392a27d88b9"},
2359f08c3bdfSopenharmony_ci		{"linux-git", "ff002b30181d"},
2360f08c3bdfSopenharmony_ci		{"known-fail", "ustat() is known to fail with EINVAL on Btrfs"},
2361f08c3bdfSopenharmony_ci		{"linux-stable-git", "c4a23c852e80"},
2362f08c3bdfSopenharmony_ci		{"CVE", "2020-29373"},
2363f08c3bdfSopenharmony_ci		{}
2364f08c3bdfSopenharmony_ci	}
2365f08c3bdfSopenharmony_ci};
2366f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
2367f08c3bdfSopenharmony_ci
2368f08c3bdfSopenharmony_ciNOTE: We don't track all backports to stable kernel but just those which are
2369f08c3bdfSopenharmony_ci      stable branch specific (unique), i.e. no commit in mainline. Example of
2370f08c3bdfSopenharmony_ci      commits: c4a23c852e80, cac68d12c531.
2371f08c3bdfSopenharmony_ci
2372f08c3bdfSopenharmony_ciGlibc and musl git commits in a regression test for glibc and musl bugs:
2373f08c3bdfSopenharmony_ci[source,c]
2374f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
2375f08c3bdfSopenharmony_cistruct tst_test test = {
2376f08c3bdfSopenharmony_ci	...
2377f08c3bdfSopenharmony_ci	.tags = (const struct tst_tag[]) {
2378f08c3bdfSopenharmony_ci		{"glibc-git", "574500a108be"},
2379f08c3bdfSopenharmony_ci		{"musl-git", "fa4a8abd06a4"},
2380f08c3bdfSopenharmony_ci		{}
2381f08c3bdfSopenharmony_ci	}
2382f08c3bdfSopenharmony_ci};
2383f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
2384f08c3bdfSopenharmony_ci
2385f08c3bdfSopenharmony_ci1.41 Testing on the specific architecture
2386f08c3bdfSopenharmony_ci~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2387f08c3bdfSopenharmony_ciTestcases for specific arch should be limited on that only being supported
2388f08c3bdfSopenharmony_ciplatform to run, we now involve a '.supported_archs' to achieve this feature
2389f08c3bdfSopenharmony_ciin LTP library. All you need to run a test on the expected arch is to set
2390f08c3bdfSopenharmony_cithe '.supported_archs' array in the 'struct tst_test' to choose the required
2391f08c3bdfSopenharmony_ciarch list. e.g.
2392f08c3bdfSopenharmony_ci
2393f08c3bdfSopenharmony_ci    .supported_archs = (const char *const []){"x86_64", "ppc64", NULL}
2394f08c3bdfSopenharmony_ci
2395f08c3bdfSopenharmony_ciThis helps move the TCONF info from code to tst_test metadata as well.
2396f08c3bdfSopenharmony_ci
2397f08c3bdfSopenharmony_ciAnd, we also export a struct tst_arch to save the system architecture for
2398f08c3bdfSopenharmony_ciusing in the whole test cases.
2399f08c3bdfSopenharmony_ci
2400f08c3bdfSopenharmony_ci    extern const struct tst_arch {
2401f08c3bdfSopenharmony_ci             char name[16];
2402f08c3bdfSopenharmony_ci             enum tst_arch_type type;
2403f08c3bdfSopenharmony_ci    } tst_arch;
2404f08c3bdfSopenharmony_ci
2405f08c3bdfSopenharmony_ci[source,c]
2406f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
2407f08c3bdfSopenharmony_ci#include "tst_test.h"
2408f08c3bdfSopenharmony_ci
2409f08c3bdfSopenharmony_cistatic struct tst_test test = {
2410f08c3bdfSopenharmony_ci       ...
2411f08c3bdfSopenharmony_ci       .setup = setup,
2412f08c3bdfSopenharmony_ci       .supported_archs = (const char *const []) {
2413f08c3bdfSopenharmony_ci                 "x86_64",
2414f08c3bdfSopenharmony_ci                 "ppc64",
2415f08c3bdfSopenharmony_ci                 "s390x",
2416f08c3bdfSopenharmony_ci                 NULL
2417f08c3bdfSopenharmony_ci       },
2418f08c3bdfSopenharmony_ci};
2419f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
2420f08c3bdfSopenharmony_ci
2421f08c3bdfSopenharmony_ci1.42 Skipping test based on system state
2422f08c3bdfSopenharmony_ci~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2423f08c3bdfSopenharmony_ciTest can be skipped on various conditions: on enabled SecureBoot
2424f08c3bdfSopenharmony_ci('.skip_in_secureboot = 1'), lockdown ('.skip_in_lockdown = 1') or in 32-bit
2425f08c3bdfSopenharmony_cicompat mode ('.skip_in_compat = 1').
2426f08c3bdfSopenharmony_ci
2427f08c3bdfSopenharmony_ci2. Common problems
2428f08c3bdfSopenharmony_ci------------------
2429f08c3bdfSopenharmony_ci
2430f08c3bdfSopenharmony_ciThis chapter describes common problems/misuses and less obvious design patters
2431f08c3bdfSopenharmony_ci(quirks) in UNIX interfaces. Read it carefully :)
2432f08c3bdfSopenharmony_ci
2433f08c3bdfSopenharmony_ci2.1 umask()
2434f08c3bdfSopenharmony_ci~~~~~~~~~~~
2435f08c3bdfSopenharmony_ci
2436f08c3bdfSopenharmony_ciI've been hit by this one several times already... When you create files
2437f08c3bdfSopenharmony_ciwith 'open()' or 'creat()' etc, the mode specified as the last parameter *is
2438f08c3bdfSopenharmony_cinot* the mode the file is created with. The mode depends on current 'umask()'
2439f08c3bdfSopenharmony_cisettings which may clear some of the bits. If your test depends on specific
2440f08c3bdfSopenharmony_cifile permissions you need either to change umask to 0 or 'chmod()' the file
2441f08c3bdfSopenharmony_ciafterwards or use 'SAFE_TOUCH()' that does the 'chmod()' for you.
2442f08c3bdfSopenharmony_ci
2443f08c3bdfSopenharmony_ci2.2 access()
2444f08c3bdfSopenharmony_ci~~~~~~~~~~~~
2445f08c3bdfSopenharmony_ci
2446f08c3bdfSopenharmony_ciIf 'access(some_file, W_OK)' is executed by root, it will return success even
2447f08c3bdfSopenharmony_ciif the file doesn't have write permission bits set (the same holds for R_OK
2448f08c3bdfSopenharmony_citoo). For sysfs files you can use 'open()' as a workaround to check file
2449f08c3bdfSopenharmony_ciread/write permissions. It might not work for other filesystems, for these you
2450f08c3bdfSopenharmony_cihave to use 'stat()', 'lstat()' or 'fstat()'.
2451f08c3bdfSopenharmony_ci
2452f08c3bdfSopenharmony_ci2.3 umount() EBUSY
2453f08c3bdfSopenharmony_ci~~~~~~~~~~~~~~~~~~
2454f08c3bdfSopenharmony_ci
2455f08c3bdfSopenharmony_ciVarious desktop daemons (gvfsd-trash is known for that) may be stupid enough
2456f08c3bdfSopenharmony_cito probe all newly mounted filesystem which results in 'umount(2)' failing
2457f08c3bdfSopenharmony_ciwith 'EBUSY'; use 'tst_umount()' described in 1.19 that retries in this case
2458f08c3bdfSopenharmony_ciinstead of plain 'umount(2)'.
2459f08c3bdfSopenharmony_ci
2460f08c3bdfSopenharmony_ci2.4 FILE buffers and fork()
2461f08c3bdfSopenharmony_ci~~~~~~~~~~~~~~~~~~~~~~~~~~~
2462f08c3bdfSopenharmony_ci
2463f08c3bdfSopenharmony_ciBe vary that if a process calls 'fork(2)' the child process inherits open
2464f08c3bdfSopenharmony_cidescriptors as well as copy of the parent memory so especially if there are
2465f08c3bdfSopenharmony_ciany open 'FILE' buffers with a data in them they may be written both by the
2466f08c3bdfSopenharmony_ciparent and children resulting in corrupted/duplicated data in the resulting
2467f08c3bdfSopenharmony_cifiles.
2468f08c3bdfSopenharmony_ci
2469f08c3bdfSopenharmony_ciAlso open 'FILE' streams are flushed and closed at 'exit(3)' so if your
2470f08c3bdfSopenharmony_ciprogram works with 'FILE' streams, does 'fork(2)', and the child may end up
2471f08c3bdfSopenharmony_cicalling 'exit(3)' you will likely end up with corrupted files.
2472f08c3bdfSopenharmony_ci
2473f08c3bdfSopenharmony_ciThe solution to this problem is either simply call 'fflush(NULL)' that flushes
2474f08c3bdfSopenharmony_ciall open output 'FILE' streams just before doing 'fork(2)'. You may also use
2475f08c3bdfSopenharmony_ci'_exit(2)' in child processes which does not flush 'FILE' buffers and also
2476f08c3bdfSopenharmony_ciskips 'atexit(3)' callbacks.
2477