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