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