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