Cyril Hrubis | afb6168 | 2014-01-13 19:08:02 +0100 | [diff] [blame] | 1 | LTP Test Writing Guidelines |
| 2 | =========================== |
| 3 | |
| 4 | This document describes LTP guidelines and LTP test interface and is intended |
| 5 | for anybody who want to write or modify a LTP testcase. It's not a definitive |
| 6 | guide and it's not, by any means, a substitute for common sense. |
| 7 | |
| 8 | |
| 9 | 1. General Rules |
| 10 | ---------------- |
| 11 | |
| 12 | 1.1 Simplicity |
| 13 | ~~~~~~~~~~~~~~ |
| 14 | |
| 15 | For all it's worth keep the testcases simple or better as simple as possible. |
Cyril Hrubis | 187e323 | 2014-02-13 14:58:07 +0100 | [diff] [blame] | 16 | The kernel and libc are tricky beasts and the complexity imposed by their |
Alexey Kodanev | 683d16e | 2014-03-27 17:28:18 +0400 | [diff] [blame] | 17 | interfaces is quite high. Concentrate on the interface you want to test and |
Cyril Hrubis | 187e323 | 2014-02-13 14:58:07 +0100 | [diff] [blame] | 18 | follow the UNIX philosophy. It's a good idea to make the test as |
| 19 | self-contained as possible too (it should not depend on tools or libraries |
| 20 | that are not widely available). |
Cyril Hrubis | afb6168 | 2014-01-13 19:08:02 +0100 | [diff] [blame] | 21 | |
| 22 | Do not reinvent the wheel |
| 23 | |
| 24 | * Use LTP standard interface |
Jiri Jaburek | 44e1ed8 | 2014-06-23 09:49:08 -0700 | [diff] [blame] | 25 | * Do not add custom PASS/FAIL reporting functions |
| 26 | * Do not write Makefiles from scratch, |
Cyril Hrubis | afb6168 | 2014-01-13 19:08:02 +0100 | [diff] [blame] | 27 | use LTP build system instead, etc. |
| 28 | * ... |
| 29 | |
| 30 | 1.2 Code duplication |
| 31 | ~~~~~~~~~~~~~~~~~~~~ |
| 32 | |
| 33 | Copy & paste is a good servant but very poor master. If you are about to copy a |
| 34 | large part of the code from one testcase to another, think what would happen if |
| 35 | you find bug in the code that has been copied all around the tree. What about |
| 36 | moving it to a library instead? |
| 37 | |
| 38 | The same goes for short but complicated parts, whenever you are about to copy & |
| 39 | paste a syscall wrapper that packs arguments accordingly to machine |
| 40 | architecture or similarly complicated code, put it into a header instead. |
| 41 | |
| 42 | 1.3 Coding style |
| 43 | ~~~~~~~~~~~~~~~~ |
| 44 | |
Cyril Hrubis | 3346379 | 2014-03-12 17:13:30 +0100 | [diff] [blame] | 45 | 1.3.1 C coding style |
| 46 | ^^^^^^^^^^^^^^^^^^^^ |
| 47 | |
Cyril Hrubis | afb6168 | 2014-01-13 19:08:02 +0100 | [diff] [blame] | 48 | LTP adopted Linux kernel coding style. If you aren't familiar with its rules |
| 49 | locate 'linux/Documentation/CodingStyle' in the kernel sources and read it, |
| 50 | it's a well written introduction. |
| 51 | |
| 52 | There is also a checkpatch (see 'linux/scripts/checkpatch.pl') script that can |
| 53 | be used to check your patches before the submission. |
| 54 | |
| 55 | NOTE: If checkpatch does not report any problems, the code still may be wrong |
| 56 | as the tool only looks for common mistakes. |
| 57 | |
Cyril Hrubis | 3346379 | 2014-03-12 17:13:30 +0100 | [diff] [blame] | 58 | 1.3.2 Shell coding style |
| 59 | ^^^^^^^^^^^^^^^^^^^^^^^^ |
| 60 | |
| 61 | When writing testcases in shell write in portable shell only, it's a good idea |
| 62 | to try to run the test using alternative shell (alternative to bash, for |
| 63 | example dash) too. |
| 64 | |
| 65 | Here are some common sense style rules for shell |
| 66 | |
| 67 | * Keep lines under 80 chars |
| 68 | |
| 69 | * Use tabs for indentation |
| 70 | |
Jiri Jaburek | 44e1ed8 | 2014-06-23 09:49:08 -0700 | [diff] [blame] | 71 | * Keep things simple, avoid unnecessary subshells |
Cyril Hrubis | 3346379 | 2014-03-12 17:13:30 +0100 | [diff] [blame] | 72 | |
| 73 | * Don't do confusing things (i.e. don't name your functions like common shell |
| 74 | commands, etc.) |
| 75 | |
| 76 | * Quote variables |
| 77 | |
| 78 | * Be consistent |
Cyril Hrubis | afb6168 | 2014-01-13 19:08:02 +0100 | [diff] [blame] | 79 | |
| 80 | 1.4 Commenting code |
| 81 | ~~~~~~~~~~~~~~~~~~~ |
| 82 | |
| 83 | Comments can sometimes save you day but they can easily do more harm than |
| 84 | good. There has been several cases where comments and actual implementation |
| 85 | were drifting slowly apart which yielded into API misuses and hard to find |
| 86 | bugs. Remember there is only one thing worse than no documentation, wrong |
| 87 | documentation. |
| 88 | |
| 89 | Generally everybody should write code that is obvious (which unfortunately |
| 90 | isn't always possible). If there is a code that needs to be commented keep it |
| 91 | short and to the point. Never ever comment the obvious. |
| 92 | |
| 93 | In case of LTP testcases it's customary to add a paragraph with highlevel test |
| 94 | description somewhere at the beginning of the file (usually right under the GPL |
| 95 | header). This helps other people to understand the overall goal of the test |
| 96 | before they dive into the technical details. |
| 97 | |
Jiri Jaburek | 44e1ed8 | 2014-06-23 09:49:08 -0700 | [diff] [blame] | 98 | 1.5 Backwards compatibility |
| 99 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
Cyril Hrubis | afb6168 | 2014-01-13 19:08:02 +0100 | [diff] [blame] | 100 | |
| 101 | LTP test should be as backward compatible as possible. Think of an enterprise |
| 102 | distributions with long term support (more than five years since the initial |
| 103 | release) or of an embedded platform that needs to use several years old |
| 104 | toolchain supplied by the manufacturer. |
| 105 | |
| 106 | Therefore LTP test for more current features should be able to cope with older |
| 107 | systems. It should at least compile fine and if it's not appropriate for the |
| 108 | configuration it should return 'TCONF' (see test interface description below). |
| 109 | |
| 110 | There are several types of checks we use: |
| 111 | |
Cyril Hrubis | 187e323 | 2014-02-13 14:58:07 +0100 | [diff] [blame] | 112 | The *configure script* is usually used to detect availability of a function |
Cyril Hrubis | afb6168 | 2014-01-13 19:08:02 +0100 | [diff] [blame] | 113 | declarations in system headers. It's used to disable tests at compile time. |
| 114 | |
| 115 | The *tst_kvercmp()* which is runtime kernel version detection and comparison |
| 116 | and is used to disable tests at runtime. |
| 117 | |
| 118 | Checking the *errno* value is another type of runtime check. Most of the |
| 119 | syscalls returns either 'EINVAL' or 'ENOSYS' when syscall was not implemented |
| 120 | or was disabled upon kernel compilation. |
| 121 | |
| 122 | Sometimes it also makes sense to define a few macros instead of creating |
| 123 | configure test. One example are Linux specific POSIX clock ids in |
| 124 | 'include/lapi/posix_clocks.h'. |
| 125 | |
| 126 | 1.6 Dealing with messed up legacy code |
| 127 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 128 | |
| 129 | LTP contains a lot of old and messy code and we are cleaning it up as fast as |
| 130 | we can but despite the efforts there is still a lot. If you start modifying |
| 131 | old or a messed up testcase and your changes are more complicated than simple |
Cyril Hrubis | 50493f6 | 2014-02-12 15:05:43 +0100 | [diff] [blame] | 132 | typo fixes you should do a cleanup first (in a separate patch). It's easier to |
Cyril Hrubis | 187e323 | 2014-02-13 14:58:07 +0100 | [diff] [blame] | 133 | review the changes if you separate the formatting fixes from the changes that |
| 134 | affects the test behavior. |
Cyril Hrubis | afb6168 | 2014-01-13 19:08:02 +0100 | [diff] [blame] | 135 | |
| 136 | The same goes for moving files. If you need a rename or move file do it in a |
| 137 | separate patch. |
| 138 | |
| 139 | 1.7 License |
| 140 | ~~~~~~~~~~~ |
| 141 | |
| 142 | Code contributed to LTP should be licensed under GPLv2+ (GNU GPL version 2 or |
| 143 | any later version). |
| 144 | |
| 145 | 2. Writing a testcase |
| 146 | --------------------- |
| 147 | |
| 148 | 2.1 LTP Structure |
| 149 | ~~~~~~~~~~~~~~~~~ |
| 150 | |
| 151 | The structure of LTP is quite simple. Each test is a binary written either in |
Jiri Jaburek | 44e1ed8 | 2014-06-23 09:49:08 -0700 | [diff] [blame] | 152 | portable shell (no bashism) or C. The test gets a configuration via |
Cyril Hrubis | afb6168 | 2014-01-13 19:08:02 +0100 | [diff] [blame] | 153 | environment variables and/or command line parameters, it prints additional |
| 154 | information into the stdout and reports overall success/failure via the exit |
| 155 | value. |
| 156 | |
| 157 | Tests are generally placed under the 'testcases/' directory. Everything that |
Cyril Hrubis | 187e323 | 2014-02-13 14:58:07 +0100 | [diff] [blame] | 158 | is a syscall or (slightly confusingly) libc syscall wrapper goes under |
Cyril Hrubis | afb6168 | 2014-01-13 19:08:02 +0100 | [diff] [blame] | 159 | 'testcases/kernel/syscalls/'. Then there is 'testcases/open_posix_testsuite' |
| 160 | which is a well maintained fork of the upstream project that has been dead |
| 161 | since 2005 and also a number of directories with tests for more specific |
| 162 | features. |
| 163 | |
| 164 | 2.1.1 Runtest Files |
| 165 | ^^^^^^^^^^^^^^^^^^^ |
| 166 | |
| 167 | The list of tests to be executed is stored in runtest files under the |
| 168 | 'runtest/' directory. The default set of runtest files to be executed is |
| 169 | stored in 'scenario_groups/default'. When you add a test you should add |
Jiri Jaburek | 44e1ed8 | 2014-06-23 09:49:08 -0700 | [diff] [blame] | 170 | corresponding entries into some runtest file(s) as well. |
Cyril Hrubis | afb6168 | 2014-01-13 19:08:02 +0100 | [diff] [blame] | 171 | |
| 172 | For syscall tests (these placed under 'testcases/kernel/syscalls/') use |
| 173 | 'runtest/syscalls' file, for kernel related tests for memory management we |
| 174 | have 'runtest/mm', etc. |
| 175 | |
Cyril Hrubis | 187e323 | 2014-02-13 14:58:07 +0100 | [diff] [blame] | 176 | IMPORTANT: The runtest files should have one entry per a test. Creating a |
| 177 | wrapper that runs all your tests and adding it as a single test |
| 178 | into runtest file is strongly discouraged. |
| 179 | |
Cyril Hrubis | afb6168 | 2014-01-13 19:08:02 +0100 | [diff] [blame] | 180 | 2.1.2 Datafiles |
| 181 | ^^^^^^^^^^^^^^^ |
| 182 | |
Jan Stancek | f423b1a | 2014-10-02 14:18:20 +0200 | [diff] [blame] | 183 | If your test needs datafiles to work, these should be put into a subdirectory |
Cyril Hrubis | 1dc9d12 | 2014-10-16 11:50:35 +0200 | [diff] [blame] | 184 | named 'datafiles' and installed into the 'testcases/data/$TCID' directory (to |
| 185 | do that you have to add 'INSTALL_DIR := testcases/data/TCID' into the |
| 186 | 'datafiles/Makefile'). |
Cyril Hrubis | afb6168 | 2014-01-13 19:08:02 +0100 | [diff] [blame] | 187 | |
Jan Stancek | f423b1a | 2014-10-02 14:18:20 +0200 | [diff] [blame] | 188 | You can obtain path to datafiles via $LTP_DATAROOT provided by test.sh |
Cyril Hrubis | 1dc9d12 | 2014-10-16 11:50:35 +0200 | [diff] [blame] | 189 | '$LTP_DATAROOT/...' |
| 190 | or via C function 'tst_dataroot()' provided by libltp: |
| 191 | |
| 192 | [source,c] |
| 193 | ------------------------------------------------------------------------------- |
| 194 | const char *dataroot = tst_dataroot(); |
| 195 | ------------------------------------------------------------------------------- |
Jan Stancek | f423b1a | 2014-10-02 14:18:20 +0200 | [diff] [blame] | 196 | |
| 197 | Datafiles can also be accessed as '$LTPROOT/testcases/data/$TCID/...', |
Cyril Hrubis | 1dc9d12 | 2014-10-16 11:50:35 +0200 | [diff] [blame] | 198 | but '$LTP_DATAROOT' and 'tst_dataroot()' are preffered as these can be used |
Jan Stancek | f423b1a | 2014-10-02 14:18:20 +0200 | [diff] [blame] | 199 | when running testcases directly in git tree as well as from install |
| 200 | location. |
| 201 | |
| 202 | The path is constructed according to these rules: |
Cyril Hrubis | 1dc9d12 | 2014-10-16 11:50:35 +0200 | [diff] [blame] | 203 | |
| 204 | 1. if '$LTPROOT' is set, return '$LTPROOT/testcases/data/$TCID' |
| 205 | 2. else if 'tst_tmpdir()' was called return '$STARTWD/datafiles' |
| 206 | (where '$STARTWD' is initial working directory as recorded by 'tst_tmdir()') |
Jan Stancek | f423b1a | 2014-10-02 14:18:20 +0200 | [diff] [blame] | 207 | 3. else return '$CWD/datafiles' |
| 208 | |
| 209 | See 'testcases/commands/ade/ldd/ldd01' for example. |
Cyril Hrubis | afb6168 | 2014-01-13 19:08:02 +0100 | [diff] [blame] | 210 | |
| 211 | 2.1.3 Subexecutables |
| 212 | ^^^^^^^^^^^^^^^^^^^^ |
| 213 | |
Jiri Jaburek | 44e1ed8 | 2014-06-23 09:49:08 -0700 | [diff] [blame] | 214 | If you test needs to execute a binary, place it in the same directory as the |
Cyril Hrubis | 187e323 | 2014-02-13 14:58:07 +0100 | [diff] [blame] | 215 | testcase and name the file starting with testname_ ('TCID_' see below). |
Jiri Jaburek | 44e1ed8 | 2014-06-23 09:49:08 -0700 | [diff] [blame] | 216 | Once the test is executed by the framework, the path to the directory with all |
| 217 | LTP binaries is added to the '$PATH' and you can execute it just by its name. |
Cyril Hrubis | afb6168 | 2014-01-13 19:08:02 +0100 | [diff] [blame] | 218 | |
Jiri Jaburek | 44e1ed8 | 2014-06-23 09:49:08 -0700 | [diff] [blame] | 219 | TIP: If you need to execute such test from the LTP tree, you can add path to |
Cyril Hrubis | 92eeadc | 2014-01-20 17:04:32 +0100 | [diff] [blame] | 220 | current directory to '$PATH' manually with: 'PATH="$PATH:$PWD" ./foo01'. |
Cyril Hrubis | afb6168 | 2014-01-13 19:08:02 +0100 | [diff] [blame] | 221 | |
Cyril Hrubis | afb6168 | 2014-01-13 19:08:02 +0100 | [diff] [blame] | 222 | 2.2 Writing a test in C |
| 223 | ~~~~~~~~~~~~~~~~~~~~~~~ |
| 224 | |
| 225 | 2.2.1 Basic test structure |
| 226 | ^^^^^^^^^^^^^^^^^^^^^^^^^^ |
| 227 | |
| 228 | Let's start with an example, following code is a simple test for a getenv(). |
| 229 | |
| 230 | [source,c] |
| 231 | ------------------------------------------------------------------------------- |
| 232 | /* |
| 233 | * This is test for basic functionality of getenv(). |
| 234 | * |
| 235 | * - create an env variable and verify that getenv() can get get it |
| 236 | * |
| 237 | * - call getenv() with nonexisting variable name, check that it returns NULL |
| 238 | */ |
| 239 | |
| 240 | #include "test.h" |
| 241 | |
| 242 | char *TCID = "getenv01"; |
Cyril Hrubis | 50493f6 | 2014-02-12 15:05:43 +0100 | [diff] [blame] | 243 | int TST_TOTAL = 2; |
Cyril Hrubis | afb6168 | 2014-01-13 19:08:02 +0100 | [diff] [blame] | 244 | |
| 245 | #define TEST_ENV "LTP_TEST_ENV" |
| 246 | #define TEST_NE_ENV "LTP_TEST_THIS_DOES_NOT_EXIST" |
| 247 | #define TEST_ENV_VAL "val" |
| 248 | |
| 249 | static void setup(void) |
| 250 | { |
| 251 | if (setenv(TEST_ENV, TEST_ENV_VAL, 1)) |
| 252 | tst_brkm(TBROK | TERRNO, NULL, "setenv() failed"); |
| 253 | } |
| 254 | |
| 255 | static void test(void) |
| 256 | { |
| 257 | char *ret; |
| 258 | |
Stanislav Kholmanskikh | d40d54c | 2014-04-10 17:50:12 +0400 | [diff] [blame] | 259 | ret = getenv(TEST_ENV); |
Cyril Hrubis | afb6168 | 2014-01-13 19:08:02 +0100 | [diff] [blame] | 260 | |
| 261 | if (ret) { |
| 262 | if (!strcmp(ret, TEST_ENV_VAL)) |
| 263 | tst_resm(TPASS, "getenv(" TEST_ENV ") = '" |
| 264 | TEST_ENV_VAL "'"); |
| 265 | else |
| 266 | tst_resm(TFAIL, "getenv(" TEST_ENV "} = '%s', " |
| 267 | "expected '" TEST_ENV_VAL "'", ret); |
| 268 | } else { |
| 269 | tst_resm(TFAIL, "getenv(" TEST_ENV ") = NULL"); |
| 270 | } |
| 271 | |
| 272 | ret = getenv(TEST_NE_ENV); |
| 273 | |
| 274 | if (ret) |
| 275 | tst_resm(TFAIL, "getenv(" TEST_NE_ENV ") = '%s'", ret); |
| 276 | else |
Stanislav Kholmanskikh | d40d54c | 2014-04-10 17:50:12 +0400 | [diff] [blame] | 277 | tst_resm(TPASS, "getenv(" TEST_NE_ENV ") = NULL"); |
Cyril Hrubis | afb6168 | 2014-01-13 19:08:02 +0100 | [diff] [blame] | 278 | } |
| 279 | |
| 280 | int main(int argc, char *argv[]) |
| 281 | { |
| 282 | const char *msg; |
| 283 | int lc; |
| 284 | |
Stanislav Kholmanskikh | d40d54c | 2014-04-10 17:50:12 +0400 | [diff] [blame] | 285 | if ((msg = parse_opts(argc, argv, NULL, NULL))) |
Cyril Hrubis | afb6168 | 2014-01-13 19:08:02 +0100 | [diff] [blame] | 286 | tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg); |
| 287 | |
| 288 | setup(); |
| 289 | |
| 290 | for (lc = 0; TEST_LOOPING(lc); lc++) |
| 291 | test(); |
| 292 | |
| 293 | tst_exit(); |
| 294 | } |
| 295 | ------------------------------------------------------------------------------- |
| 296 | |
| 297 | Each test must define 'TCID' and 'TST_TOTAL'. |
| 298 | |
| 299 | 'TCID' defines test name (usually syscall/libcall name + number) and is used |
| 300 | as a base for temporary directory name (if 'tst_tmpdir()' is used). In most of |
| 301 | the cases the 'TCID' is the same as test filename (without the extension). |
| 302 | |
| 303 | 'TST_TOTAL' defines total number of tests. |
| 304 | |
| 305 | NOTE: The test should report 'TST_TOTAL' PASSES/FAILS on each iteration. |
| 306 | |
| 307 | The overall test initialization is usually done in a 'setup()' function and |
| 308 | the overall cleanup is done in a 'cleanup()' function. Here 'cleanup()' is |
| 309 | omitted as the test don't have to clean anything up. Usually it's called right |
| 310 | before the 'tst_exit()' to do the cleanup and passed to library functions that |
| 311 | can exit the test execution, for example 'tst_brkm()', so that the test can do |
| 312 | a cleanup before it exits. |
| 313 | |
| 314 | WARNING: Never pass a cleanup function to functions called from cleanup. |
| 315 | If you don't see why this is a problem you are not ready to write |
| 316 | a testcase yet. |
| 317 | |
Cyril Hrubis | 187e323 | 2014-02-13 14:58:07 +0100 | [diff] [blame] | 318 | WARNING: Don't use 'tst_brkm()' in 'cleanup()' unless you really want to exit |
| 319 | the cleanup prematurely. See discussion below for further |
| 320 | information. |
| 321 | |
Cyril Hrubis | afb6168 | 2014-01-13 19:08:02 +0100 | [diff] [blame] | 322 | The 'parse_opts()' parses the test command line arguments, it's important to |
| 323 | use it even if the test has no (other than default) parameters. |
| 324 | |
| 325 | The last important thing is the 'TEST_LOOPING()' macro, each test has standard |
| 326 | options so that it can be executed N times or for M seconds. |
| 327 | |
| 328 | NOTE: The 'test()' function must work correctly even if executed several times |
| 329 | from test main loop. |
| 330 | |
Cyril Hrubis | d2d64cf | 2014-02-12 18:12:16 +0100 | [diff] [blame] | 331 | A word about the cleanup() callback |
| 332 | +++++++++++++++++++++++++++++++++++ |
| 333 | |
| 334 | There are a few rules that needs to be followed in order to write correct |
| 335 | cleanup() callback. |
| 336 | |
| 337 | 1. Don't call callback() from within the callback(). |
| 338 | (This includes passing callback pointer to library 'tst_' functions.) |
| 339 | |
Cyril Hrubis | 187e323 | 2014-02-13 14:58:07 +0100 | [diff] [blame] | 340 | 2. Make sure to free resources in the reverse order they were |
Cyril Hrubis | d2d64cf | 2014-02-12 18:12:16 +0100 | [diff] [blame] | 341 | initialized. (Some of the steps may not depend on others and everything |
| 342 | will work if there were swapped but let's keep it in order.) |
| 343 | |
Cyril Hrubis | 187e323 | 2014-02-13 14:58:07 +0100 | [diff] [blame] | 344 | 3. Free only resources that were initialized. |
Cyril Hrubis | d2d64cf | 2014-02-12 18:12:16 +0100 | [diff] [blame] | 345 | |
| 346 | The third rule needs a bit more detailed discussion. Consider, for example, |
| 347 | test setup below which is example of a setup that prepares temporary |
| 348 | directory, two file descriptors and allocates a buffer. |
| 349 | |
| 350 | [source,c] |
| 351 | ------------------------------------------------------------------------------- |
| 352 | static int fd0, fd1; |
| 353 | static void *buf; |
| 354 | #define BUFSIZE (1024 * 1024) |
| 355 | |
| 356 | static void setup(void) |
| 357 | { |
| 358 | tst_require_root(); |
| 359 | tst_tmpdir(); |
| 360 | |
| 361 | fd0 = SAFE_OPEN(cleanup, "test_file1", O_CREAT | O_RDWR, 0666); |
| 362 | SAFE_UNLINK(cleanup, "test_file1"); |
| 363 | fd1 = SAFE_OPEN(cleanup, "test_file2", O_CREAT | O_RDWR, 0666); |
| 364 | SAFE_UNLINK(cleanup, "test_file2"); |
| 365 | |
| 366 | buf = SAFE_MALLOC(cleanup, BUFSIZE); |
| 367 | } |
| 368 | ------------------------------------------------------------------------------- |
| 369 | |
| 370 | In this case the 'cleanup()' function may be entered in five different states: |
| 371 | |
Cyril Hrubis | 187e323 | 2014-02-13 14:58:07 +0100 | [diff] [blame] | 372 | * The first 'SAFE_OPEN()' has failed, temporary directory is created |
Cyril Hrubis | d2d64cf | 2014-02-12 18:12:16 +0100 | [diff] [blame] | 373 | no files are open and +fd0 == -1+, +fd1 == 0+ and +buf == NULL+. |
| 374 | |
| 375 | * The first 'SAFE_UNLINK()' has failed, +fd0+ holds file descriptor and |
| 376 | +fd1 == 0+. |
| 377 | |
Cyril Hrubis | 187e323 | 2014-02-13 14:58:07 +0100 | [diff] [blame] | 378 | * The second 'SAFE_OPEN()' has failed, +fd0+ holds file descriptor and |
Cyril Hrubis | d2d64cf | 2014-02-12 18:12:16 +0100 | [diff] [blame] | 379 | +fd1 == -1+. |
| 380 | |
| 381 | * The second 'SAFE_UNLINK()' or 'SAFE_MALLOC()' has failed and both 'fd0' and |
| 382 | 'fd1' holds file descriptors, +buf+ is still +NULL+. |
| 383 | |
| 384 | * The 'cleanup()' was called at the end of the test, all +fd0+, +fd1+ and |
| 385 | +buf+ are initialized. |
| 386 | |
| 387 | The 'cleanup()' functions should be able to cope with all scenarios. In this |
| 388 | case following code will do: |
| 389 | |
| 390 | [source,c] |
| 391 | ------------------------------------------------------------------------------- |
| 392 | static void cleanup(void) |
| 393 | { |
Cyril Hrubis | 187e323 | 2014-02-13 14:58:07 +0100 | [diff] [blame] | 394 | free(buf); |
Cyril Hrubis | d2d64cf | 2014-02-12 18:12:16 +0100 | [diff] [blame] | 395 | |
| 396 | if (fd1 > 0) |
| 397 | close(fd1); |
| 398 | |
| 399 | if (fd0 > 0) |
| 400 | close(fd0); |
| 401 | |
| 402 | tst_rmdir(); |
| 403 | } |
| 404 | ------------------------------------------------------------------------------- |
Cyril Hrubis | afb6168 | 2014-01-13 19:08:02 +0100 | [diff] [blame] | 405 | |
| 406 | 2.2.2 Basic test interface |
| 407 | ^^^^^^^^^^^^^^^^^^^^^^^^^^ |
| 408 | |
| 409 | [source,c] |
| 410 | ------------------------------------------------------------------------------- |
| 411 | void tst_resm(int ttype, char *arg_fmt, ...); |
| 412 | ------------------------------------------------------------------------------- |
| 413 | |
| 414 | Printf-like function to report test result, it's mostly used with ttype: |
| 415 | |
| 416 | |============================== |
| 417 | | 'TPASS' | Test has passed. |
| 418 | | 'TFAIL' | Test has failed. |
| 419 | | 'TINFO' | General message. |
| 420 | |============================== |
| 421 | |
Cyril Hrubis | 2197743 | 2014-05-29 18:47:03 +0200 | [diff] [blame] | 422 | The 'ttype' can be combined bitwise with 'TERRNO' or 'TTERRNO' to print |
| 423 | 'errno', 'TEST_ERRNO' respectively. |
| 424 | |
Cyril Hrubis | afb6168 | 2014-01-13 19:08:02 +0100 | [diff] [blame] | 425 | [source,c] |
| 426 | ------------------------------------------------------------------------------- |
| 427 | void tst_brkm(int ttype, void (*cleanup)(void), char *arg_fmt, ...); |
| 428 | ------------------------------------------------------------------------------- |
| 429 | |
| 430 | Printf-like function to report error and exit the test, it can be used with ttype: |
| 431 | |
| 432 | |============================================================ |
| 433 | | 'TBROK' | Something has failed in test preparation phase. |
| 434 | | 'TCONF' | test is not appropriate for current configuration |
| 435 | (syscall not implemented, unsupported arch, ...) |
| 436 | | 'TFAIL' | test has failed |
| 437 | |============================================================ |
| 438 | |
Cyril Hrubis | 2197743 | 2014-05-29 18:47:03 +0200 | [diff] [blame] | 439 | The 'ttype' can be combined bitwise with 'TERRNO' or 'TTERRNO' to print |
| 440 | 'errno', 'TEST_ERRNO' respectively. |
Cyril Hrubis | afb6168 | 2014-01-13 19:08:02 +0100 | [diff] [blame] | 441 | |
| 442 | [source,c] |
| 443 | ------------------------------------------------------------------------------- |
| 444 | void tst_require_root(void (*cleanup)(void)); |
| 445 | ------------------------------------------------------------------------------- |
| 446 | |
| 447 | Abort the test if it's not executed with root privileges. If needed this should |
| 448 | be one of the first checks in the test 'setup()'. |
| 449 | |
| 450 | WARNING: The cleanup parameter is deprecated and should always be 'NULL'. |
| 451 | |
| 452 | |
| 453 | [source,c] |
| 454 | ------------------------------------------------------------------------------- |
| 455 | void tst_exit(void); |
| 456 | ------------------------------------------------------------------------------- |
| 457 | |
| 458 | Exits the tests, note that this function has no parameters, the PASSES/FAILS |
| 459 | reported by the 'tst_resm()' interfaces were stored and are used for the exit |
| 460 | value. |
| 461 | |
Xiaoguang Wang | ef72ef8 | 2014-05-14 13:16:39 +0800 | [diff] [blame] | 462 | [source,c] |
| 463 | ------------------------------------------------------------------------------- |
| 464 | const char *tst_strsig(int sig); |
| 465 | ------------------------------------------------------------------------------- |
| 466 | |
| 467 | Return the given signal number's corresponding string. |
| 468 | |
| 469 | |
| 470 | [source,c] |
| 471 | ------------------------------------------------------------------------------- |
| 472 | const char *tst_strerrno(int err); |
| 473 | ------------------------------------------------------------------------------- |
| 474 | |
| 475 | Return the given errno number's corresponding string. |
| 476 | |
Cyril Hrubis | afb6168 | 2014-01-13 19:08:02 +0100 | [diff] [blame] | 477 | |
| 478 | 2.2.3 Test temporary directory |
| 479 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
| 480 | |
| 481 | If the test needs to create files (which is common case) it must create a test |
| 482 | temporary directory in LTP temp directory and work with files only inside of |
| 483 | this directory. Happily there are easy to use library functions exactly for |
| 484 | this purpose. |
| 485 | |
| 486 | [source,c] |
| 487 | ------------------------------------------------------------------------------- |
| 488 | void tst_tmpdir(void); |
| 489 | ------------------------------------------------------------------------------- |
| 490 | |
| 491 | Creates a directory with a unique name (based on the test 'TCID') under the |
| 492 | LTP temporary directory (defaults to '/tmp/') and changes the test working |
| 493 | directory to it. It's usually called from the test 'setup()'. |
| 494 | |
| 495 | [source,c] |
| 496 | ------------------------------------------------------------------------------- |
| 497 | void tst_rmdir(void); |
| 498 | ------------------------------------------------------------------------------- |
| 499 | |
Cyril Hrubis | 187e323 | 2014-02-13 14:58:07 +0100 | [diff] [blame] | 500 | Removes the directory recursively. It's usually called from test 'cleanup()'. |
Cyril Hrubis | afb6168 | 2014-01-13 19:08:02 +0100 | [diff] [blame] | 501 | |
Jiri Jaburek | cc595b1 | 2014-06-23 10:30:03 -0700 | [diff] [blame] | 502 | It's important to close all file descriptors (that point to files in test |
Cyril Hrubis | 50493f6 | 2014-02-12 15:05:43 +0100 | [diff] [blame] | 503 | temporary directory, even the unlinked ones) before the test calls |
Cyril Hrubis | afb6168 | 2014-01-13 19:08:02 +0100 | [diff] [blame] | 504 | 'tst_rmdir()' otherwise the test may break on NFS mounted temp dir (look for |
| 505 | "NFS silly rename"). |
| 506 | |
Xiaoguang Wang | 3e15bd7 | 2014-07-28 19:51:40 +0800 | [diff] [blame] | 507 | [[2.2.4]] |
Cyril Hrubis | afb6168 | 2014-01-13 19:08:02 +0100 | [diff] [blame] | 508 | 2.2.4 Safe macros |
| 509 | ^^^^^^^^^^^^^^^^^ |
| 510 | |
Jiri Jaburek | cc595b1 | 2014-06-23 10:30:03 -0700 | [diff] [blame] | 511 | Safe macros aim to simplify error checking in test preparation. Instead of |
Cyril Hrubis | afb6168 | 2014-01-13 19:08:02 +0100 | [diff] [blame] | 512 | calling system API functions, checking for their return value and aborting the |
Jiri Jaburek | cc595b1 | 2014-06-23 10:30:03 -0700 | [diff] [blame] | 513 | test if the operation has failed, you just use corresponding safe macros. |
Cyril Hrubis | afb6168 | 2014-01-13 19:08:02 +0100 | [diff] [blame] | 514 | |
| 515 | Use them whenever it's possible. |
| 516 | |
Xiaoguang Wang | 3e15bd7 | 2014-07-28 19:51:40 +0800 | [diff] [blame] | 517 | NOTE: Have a look at the the xref:2.2.7[doing real test in the child process] |
| 518 | if you want to use safe macros from within a child process. |
Cyril Hrubis | afb6168 | 2014-01-13 19:08:02 +0100 | [diff] [blame] | 519 | |
| 520 | Instead of writing: |
| 521 | |
| 522 | [source,c] |
| 523 | ------------------------------------------------------------------------------- |
| 524 | fd = open("/dev/null", O_RDONLY); |
| 525 | if (fd < 0) |
| 526 | tst_brkm(TBROK | TERRNO, cleanup, "opening /dev/null failed"); |
| 527 | ------------------------------------------------------------------------------- |
| 528 | |
| 529 | You write just: |
| 530 | |
| 531 | [source,c] |
| 532 | ------------------------------------------------------------------------------- |
| 533 | fd = SAFE_OPEN(cleanup, "/dev/null", O_RDONLY); |
| 534 | ------------------------------------------------------------------------------- |
| 535 | |
| 536 | They can also simplify reading and writing of sysfs files, you can, for |
Jiri Jaburek | cc595b1 | 2014-06-23 10:30:03 -0700 | [diff] [blame] | 537 | example, do: |
Cyril Hrubis | afb6168 | 2014-01-13 19:08:02 +0100 | [diff] [blame] | 538 | |
| 539 | [source,c] |
| 540 | ------------------------------------------------------------------------------- |
| 541 | SAFE_FILE_SCANF(cleanup, "/proc/sys/kernel/pid_max", "%lu", &pid_max); |
| 542 | ------------------------------------------------------------------------------- |
| 543 | |
| 544 | See 'include/safe_macros.h', 'include/safe_stdio.h' and |
| 545 | 'include/safe_file_ops.h' for a complete list. |
| 546 | |
Cyril Hrubis | 50493f6 | 2014-02-12 15:05:43 +0100 | [diff] [blame] | 547 | NOTE: It's wise NOT to use safe macros in test cleanup(). This is because |
Jiri Jaburek | cc595b1 | 2014-06-23 10:30:03 -0700 | [diff] [blame] | 548 | all safe macros call tst_brkm(), which exits the test immediately, making |
| 549 | the cleanup() exit prematurely. (Actually, this is hacked around in |
Cyril Hrubis | 50493f6 | 2014-02-12 15:05:43 +0100 | [diff] [blame] | 550 | the test library at the moment so that the cleanup() will finish, but |
| 551 | the hack will be removed in the future). |
| 552 | |
Cyril Hrubis | ddd3b85 | 2014-02-03 17:10:04 +0100 | [diff] [blame] | 553 | 2.2.5 Runtime kernel version detection |
| 554 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
Cyril Hrubis | afb6168 | 2014-01-13 19:08:02 +0100 | [diff] [blame] | 555 | |
| 556 | [source,c] |
| 557 | ------------------------------------------------------------------------------- |
| 558 | int tst_kvercmp(int r1, int r2, int r3); |
| 559 | |
| 560 | struct tst_kern_exv { |
| 561 | char *dist_name; |
| 562 | char *extra_ver; |
| 563 | }; |
| 564 | |
| 565 | int tst_kvercmp2(int r1, int r2, int r3, struct tst_kern_exv *vers); |
| 566 | ------------------------------------------------------------------------------- |
| 567 | |
| 568 | These two functions are intended for runtime kernel version detection. They |
Jiri Jaburek | cc595b1 | 2014-06-23 10:30:03 -0700 | [diff] [blame] | 569 | parse the output from 'uname()' and compare it to the passed values. |
Cyril Hrubis | afb6168 | 2014-01-13 19:08:02 +0100 | [diff] [blame] | 570 | |
| 571 | The return value is similar to the 'strcmp()' function, i.e. zero means equal, |
| 572 | negative value means that the kernel is older than than the expected value and |
| 573 | positive means that it's newer. |
| 574 | |
| 575 | The second function 'tst_kvercmp2()' allows for specifying per-vendor table of |
| 576 | kernel versions as vendors typically backport fixes to their kernels and the |
| 577 | test may be relevant even if the kernel version does not suggests so. See |
| 578 | 'testcases/kernel/syscalls/inotify/inotify04.c' for example usage. |
| 579 | |
Cyril Hrubis | ddd3b85 | 2014-02-03 17:10:04 +0100 | [diff] [blame] | 580 | 2.2.6 Fork()-ing |
| 581 | ^^^^^^^^^^^^^^^^ |
| 582 | |
Cyril Hrubis | 124c987 | 2014-07-03 17:24:38 +0200 | [diff] [blame] | 583 | Be wary that if the test forks and there were messages printed by the tst_* |
Jiri Jaburek | cc595b1 | 2014-06-23 10:30:03 -0700 | [diff] [blame] | 584 | interfaces, the data may still be in kernel buffers and these are NOT flushed |
Cyril Hrubis | ddd3b85 | 2014-02-03 17:10:04 +0100 | [diff] [blame] | 585 | automatically. |
| 586 | |
Jiri Jaburek | cc595b1 | 2014-06-23 10:30:03 -0700 | [diff] [blame] | 587 | This happens when 'stdout' gets redirected to a file. In this case, the |
| 588 | 'stdout' is not line buffered, but block buffered, and buffered messages will be |
| 589 | printed by the parent and each of the children. |
Cyril Hrubis | ddd3b85 | 2014-02-03 17:10:04 +0100 | [diff] [blame] | 590 | |
Jiri Jaburek | cc595b1 | 2014-06-23 10:30:03 -0700 | [diff] [blame] | 591 | To avoid that, you should either call 'tst_flush()' right before the 'fork()', |
| 592 | or even better - use 'tst_fork()' instead. |
Cyril Hrubis | ddd3b85 | 2014-02-03 17:10:04 +0100 | [diff] [blame] | 593 | |
Xiaoguang Wang | 3e15bd7 | 2014-07-28 19:51:40 +0800 | [diff] [blame] | 594 | [[2.2.7]] |
| 595 | 2.2.7 Doing real test in the child process |
| 596 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
| 597 | |
| 598 | If you have to do the test in a child process you have two possibilities: |
| 599 | |
| 600 | * You can use test interface ('tst_resm()', 'tst_brkm()', 'tst_exit()', ...) |
| 601 | but there are some rules to obey: |
| 602 | |
| 603 | ** If you use 'tst_resm()' to record test the results in child process, you |
| 604 | *MUST* use either 'tst_exit()' or 'tst_brkm()' to exit the child process. |
| 605 | |
| 606 | ** If you use 'tst_brkm()' with a non-NULL cleanup argument in the child |
| 607 | process, you're strongly recommended to create a separate cleanup function |
| 608 | for child process that will only clean up what has been allocated in child |
| 609 | process. Otherwise the 'cleanup()' will be called both from the parent and |
| 610 | child and the test will likely fail (for example in 'tst_rmdir()' because |
| 611 | both parent and child will attempt to remove the directory and one of them |
| 612 | will fail). |
| 613 | |
| 614 | ** The same applies to xref:2.2.4[safe macros] because they call 'tst_brkm()' |
| 615 | when anything goes wrong. |
| 616 | |
| 617 | * Or you can stick to plain old 'exit()' with 'TPASS', 'TBROK', 'TFAIL' and |
| 618 | 'TCONF' constants. |
| 619 | |
| 620 | Then you call 'tst_record_childstatus()' to records the result of the test |
| 621 | (done in child process) which propagates the child result (child exit status) |
| 622 | to the parent process correctly. |
| 623 | |
| 624 | [source,c] |
| 625 | ------------------------------------------------------------------------------- |
| 626 | #include "test.h" |
| 627 | |
| 628 | void tst_record_childstatus(void (*cleanup)(void), pid_t child); |
| 629 | ------------------------------------------------------------------------------- |
| 630 | |
| 631 | This function does a 'waitpid()' on child process and record child process's |
| 632 | return value into the overall test result. |
| 633 | |
| 634 | 2.2.8 Fork() and Parent-child synchronization |
Cyril Hrubis | afb6168 | 2014-01-13 19:08:02 +0100 | [diff] [blame] | 635 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
| 636 | |
Jiri Jaburek | cc595b1 | 2014-06-23 10:30:03 -0700 | [diff] [blame] | 637 | As LTP tests are written for Linux, most of the test involves fork()-ing and |
Xiaoguang Wang | 3e15bd7 | 2014-07-28 19:51:40 +0800 | [diff] [blame] | 638 | parent-child process synchronization. We have a checkpoint library code |
Cyril Hrubis | afb6168 | 2014-01-13 19:08:02 +0100 | [diff] [blame] | 639 | that works even for two different processes, all they need to is to run with |
| 640 | the same working directory (they use FIFO for synchronization). The checkpoint |
Jiri Jaburek | cc595b1 | 2014-06-23 10:30:03 -0700 | [diff] [blame] | 641 | interface provides two pairs of signal and wait functions. One pair to be used |
Cyril Hrubis | afb6168 | 2014-01-13 19:08:02 +0100 | [diff] [blame] | 642 | to signal child from parent and second to signal parent from child. |
| 643 | |
Jan Stancek | a4bb6db | 2014-10-17 09:38:00 +0200 | [diff] [blame] | 644 | Checkpoint is represented by 'struct tst_checkpoint', which has to be |
| 645 | initialized before first usage and FIFO has to be created. This is |
| 646 | usually done in parent process in single step by calling |
| 647 | 'tst_checkpoint_create()'. |
| 648 | |
| 649 | Child processes created via fork() are ready to use tst_checkpoint_* |
| 650 | synchronization functions, as they inherited already initialized |
| 651 | 'struct tst_checkpoint'. |
| 652 | |
| 653 | Child processes started via exec*, or any other process can use already |
| 654 | created FIFO, provided they initialize 'struct tst_checkpoint' first by |
| 655 | call to 'tst_checkpoint_init()'. This function does not create any FIFO, |
| 656 | it relies on fact, that it was already created by some other process. |
| 657 | Note, that if you use multiple FIFOs in this scenario, these should be |
| 658 | initialized in same order as in process you are sychronizing against. |
| 659 | |
| 660 | IMPORTANT: Be aware, that following scenario is _NOT_ safe when using |
| 661 | only single checkpoint. You are advised to use two checkpoints |
| 662 | in this case. |
| 663 | |
| 664 | * tst_checkpoint_signal_child() followed by tst_checkpoint_parent_wait() |
| 665 | |
| 666 | parent | child |
| 667 | -------------------------------+------------------------------- |
| 668 | | tst_checkpoint_child_wait() |
| 669 | | blocking read, waits until |
| 670 | | parent opens write side |
| 671 | tst_checkpoint_signal_child() | |
| 672 | NONBLOCK write | |
| 673 | | child is now able to read |
| 674 | | from FIFO |
| 675 | tst_checkpoint_parent_wait() | |
| 676 | NONBLOCK read parent able to | |
| 677 | read from FIFO and can race | |
| 678 | with read in child | |
| 679 | | tst_checkpoint_signal_parent() |
| 680 | -------------------------------+-------------------------------- |
| 681 | |
Jiri Jaburek | cc595b1 | 2014-06-23 10:30:03 -0700 | [diff] [blame] | 682 | For the details of the interface, look into the 'include/tst_checkpoint.h' and |
Cyril Hrubis | afb6168 | 2014-01-13 19:08:02 +0100 | [diff] [blame] | 683 | 'lib/tests/tst_checkpoint_*'. |
| 684 | |
| 685 | There is also an interface that allows parent to wait until child is blocked |
Jiri Jaburek | cc595b1 | 2014-06-23 10:30:03 -0700 | [diff] [blame] | 686 | in kernel (for example waits in 'pause()'), see 'include/tst_process_state.h' |
Cyril Hrubis | afb6168 | 2014-01-13 19:08:02 +0100 | [diff] [blame] | 687 | for more. |
| 688 | |
Xiaoguang Wang | 3e15bd7 | 2014-07-28 19:51:40 +0800 | [diff] [blame] | 689 | 2.2.9 Signal handlers |
Cyril Hrubis | 12563f9 | 2014-02-03 17:55:41 +0100 | [diff] [blame] | 690 | ^^^^^^^^^^^^^^^^^^^^^ |
| 691 | |
Jiri Jaburek | cc595b1 | 2014-06-23 10:30:03 -0700 | [diff] [blame] | 692 | If you need to use signal handlers, keep the code short and simple. Don't |
Cyril Hrubis | 124c987 | 2014-07-03 17:24:38 +0200 | [diff] [blame] | 693 | forget that the signal handler is called asynchronously and can interrupt the |
| 694 | code execution at any place. |
Cyril Hrubis | 12563f9 | 2014-02-03 17:55:41 +0100 | [diff] [blame] | 695 | |
Cyril Hrubis | 124c987 | 2014-07-03 17:24:38 +0200 | [diff] [blame] | 696 | This means that problems arise when global state is changed both from the test |
| 697 | code and signal handler, which will occasionally lead to: |
Jiri Jaburek | cc595b1 | 2014-06-23 10:30:03 -0700 | [diff] [blame] | 698 | |
Cyril Hrubis | 124c987 | 2014-07-03 17:24:38 +0200 | [diff] [blame] | 699 | * Data corruption (data gets into inconsistent state), this may happen, for |
| 700 | example, for any operations on 'FILE' objects. |
| 701 | |
| 702 | * Deadlock, this happens, for example, if you call 'malloc(2)', 'free(2)', |
| 703 | etc. from both the test code and the signal handler at the same time because |
| 704 | 'malloc' has global lock for it's internal data structures. (Be wary that |
| 705 | 'malloc(2)' is used by the libc functions internally too.) |
| 706 | |
| 707 | * Any other unreproducible and unexpected behavior. |
Cyril Hrubis | 12563f9 | 2014-02-03 17:55:41 +0100 | [diff] [blame] | 708 | |
Cyril Hrubis | 187e323 | 2014-02-13 14:58:07 +0100 | [diff] [blame] | 709 | Quite common mistake is to call 'exit(3)' from a signal handler. Note that this |
Cyril Hrubis | 12563f9 | 2014-02-03 17:55:41 +0100 | [diff] [blame] | 710 | function is not signal-async-safe as it flushes buffers, etc. If you need to |
| 711 | exit a test immediately from a signal handler use '_exit(2)' instead. |
| 712 | |
Jiri Jaburek | cc595b1 | 2014-06-23 10:30:03 -0700 | [diff] [blame] | 713 | TIP: See 'man 7 signal' for the list of signal-async-safe functions. |
Cyril Hrubis | 12563f9 | 2014-02-03 17:55:41 +0100 | [diff] [blame] | 714 | |
Jiri Jaburek | cc595b1 | 2014-06-23 10:30:03 -0700 | [diff] [blame] | 715 | If a signal handler sets a variable, its declaration must be 'volatile', |
| 716 | otherwise compiler may misoptimize the code, because the variable may not be |
Cyril Hrubis | 187e323 | 2014-02-13 14:58:07 +0100 | [diff] [blame] | 717 | changed in the code flow analysis. There is 'sig_atomic_t' type defined in C99 |
Jiri Jaburek | cc595b1 | 2014-06-23 10:30:03 -0700 | [diff] [blame] | 718 | but this one DOES NOT imply volatile (it's just a typedef to int). So the |
| 719 | correct type for a flag that is changed from a signal handler is either |
| 720 | 'volatile int' or 'volatile sig_atomic_t'. |
Cyril Hrubis | 12563f9 | 2014-02-03 17:55:41 +0100 | [diff] [blame] | 721 | |
Xiaoguang Wang | 3e15bd7 | 2014-07-28 19:51:40 +0800 | [diff] [blame] | 722 | 2.2.10 Kernel Modules |
| 723 | ^^^^^^^^^^^^^^^^^^^^^ |
Cyril Hrubis | afb6168 | 2014-01-13 19:08:02 +0100 | [diff] [blame] | 724 | |
Jiri Jaburek | cc595b1 | 2014-06-23 10:30:03 -0700 | [diff] [blame] | 725 | There are certain cases where the test needs a kernel part and userspace part, |
| 726 | happily, LTP can build a kernel module and then insert it to the kernel on test |
Cyril Hrubis | afb6168 | 2014-01-13 19:08:02 +0100 | [diff] [blame] | 727 | start for you. See 'testcases/kernel/device-drivers/block' for details. |
| 728 | |
Xiaoguang Wang | 3e15bd7 | 2014-07-28 19:51:40 +0800 | [diff] [blame] | 729 | 2.2.11 Usefull macros |
Cyril Hrubis | 50493f6 | 2014-02-12 15:05:43 +0100 | [diff] [blame] | 730 | ^^^^^^^^^^^^^^^^^^^^^ |
| 731 | |
| 732 | [source,c] |
| 733 | ------------------------------------------------------------------------------- |
| 734 | ARRAY_SIZE(arr) |
| 735 | ------------------------------------------------------------------------------- |
| 736 | |
| 737 | Returns the size of statically defined array, i.e. |
| 738 | '(sizeof(arr) / sizeof(*arr))' |
| 739 | |
| 740 | [source,c] |
| 741 | ------------------------------------------------------------------------------- |
| 742 | LTP_ALIGN(x, a) |
| 743 | ------------------------------------------------------------------------------- |
| 744 | |
| 745 | Aligns the x to be next multiple of a. The a must be power of 2. |
Cyril Hrubis | afb6168 | 2014-01-13 19:08:02 +0100 | [diff] [blame] | 746 | |
Xiaoguang Wang | 3e15bd7 | 2014-07-28 19:51:40 +0800 | [diff] [blame] | 747 | 2.2.12 Filesystem type detection |
Cyril Hrubis | 0f0e348 | 2014-02-27 16:08:04 +0100 | [diff] [blame] | 748 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
| 749 | |
| 750 | Some tests are known to fail on certain filesytems (you cannot swap on TMPFS, |
| 751 | there are unimplemented fcntl() etc.). |
| 752 | |
Jiri Jaburek | cc595b1 | 2014-06-23 10:30:03 -0700 | [diff] [blame] | 753 | If your test needs to be skipped on certain filesystems, use the interface |
| 754 | below: |
Cyril Hrubis | 0f0e348 | 2014-02-27 16:08:04 +0100 | [diff] [blame] | 755 | |
| 756 | [source,c] |
| 757 | ------------------------------------------------------------------------------- |
| 758 | #include "tst_fs_type.h" |
| 759 | |
| 760 | /* |
| 761 | * Unsupported only on NFS. |
| 762 | */ |
| 763 | if (tst_fs_type(cleanup, ".") == TST_NFS_MAGIC) { |
| 764 | tst_brkm(TCONF, cleanup, |
| 765 | "Test not supported on NFS filesystem"); |
| 766 | } |
| 767 | |
| 768 | /* |
| 769 | * Unsupported on NFS, TMPFS and RAMFS |
| 770 | */ |
| 771 | long type; |
| 772 | |
| 773 | switch ((type = tst_fs_type(cleanup, "."))) { |
| 774 | case TST_NFS_MAGIC: |
| 775 | case TST_TMPFS_MAGIC: |
| 776 | case TST_RAMFS_MAGIC: |
| 777 | tst_brkm(TCONF, cleanup, "Test not supported on %s filesytem", |
| 778 | tst_fs_type_name(type)); |
| 779 | break; |
| 780 | } |
| 781 | ------------------------------------------------------------------------------- |
| 782 | |
Xiaoguang Wang | 3e15bd7 | 2014-07-28 19:51:40 +0800 | [diff] [blame] | 783 | 2.2.13 Thread-safety in the LTP library |
Alexey Kodanev | 683d16e | 2014-03-27 17:28:18 +0400 | [diff] [blame] | 784 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
| 785 | |
| 786 | It is safe to use library 'tst_' functions in multi-threaded tests. |
| 787 | Synchronization mechanism is enabled only if the test is linked with pthread |
| 788 | library, otherwise no-op stubs (defined in libc) are used. |
| 789 | |
| 790 | Also, LTP has a helper "TST_DECLARE_ONCE_FN" macro to declare a function which |
| 791 | must be run only once (e.g. init or cleanup function), but might be called by |
| 792 | multiple threads at the same time. See example below: |
| 793 | |
| 794 | [source,c] |
| 795 | ------------------------------------------------------------------------------- |
| 796 | #include "test.h" |
| 797 | |
| 798 | ... |
| 799 | |
| 800 | void do_cleanup(void) |
| 801 | { |
| 802 | /* cleanup code */ |
| 803 | ... |
| 804 | } |
| 805 | TST_DECLARE_ONCE_FN(cleanup, do_cleanup); |
| 806 | |
| 807 | ... |
| 808 | |
| 809 | void test01(void) |
| 810 | { |
| 811 | sfd = socket(AF_INET, SOCK_STREAM, 0); |
| 812 | if (sfd == -1) |
| 813 | tst_brkm(TBROK, cleanup, "Failed to create a socket"); |
| 814 | } |
| 815 | ------------------------------------------------------------------------------- |
| 816 | |
Xiaoguang Wang | 3e15bd7 | 2014-07-28 19:51:40 +0800 | [diff] [blame] | 817 | 2.2.14 Acquiring a block device |
Cyril Hrubis | 85e787e | 2014-06-18 17:09:21 +0200 | [diff] [blame] | 818 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
| 819 | |
| 820 | Some tests needs a block device (inotify tests, syscall 'EROFS' failures, |
| 821 | etc.). For your convenience LTP library includes a function to acquire and |
| 822 | release a testing device. |
| 823 | |
| 824 | [source,c] |
| 825 | ------------------------------------------------------------------------------- |
| 826 | #include "test.h" |
| 827 | |
| 828 | const char *tst_acquire_device(void (cleanup_fn)(void)); |
| 829 | ------------------------------------------------------------------------------- |
| 830 | |
| 831 | This function returns a path to small block device suitable for formatting and |
| 832 | mounting. |
| 833 | |
| 834 | WARNING: You can acquire only one device, calling it for second time without |
| 835 | releasing the device first will abort the test. |
| 836 | |
Jiri Jaburek | 1f5eb34 | 2014-06-24 02:45:12 -0700 | [diff] [blame] | 837 | In case that 'LTP_DEV' is passed to the test in environment, the function just |
| 838 | checks that the file exists and that it's a block device. |
Cyril Hrubis | 85e787e | 2014-06-18 17:09:21 +0200 | [diff] [blame] | 839 | |
Jiri Jaburek | 1f5eb34 | 2014-06-24 02:45:12 -0700 | [diff] [blame] | 840 | Otherwise a temporary file is created and attached to a free loop device. |
Cyril Hrubis | 85e787e | 2014-06-18 17:09:21 +0200 | [diff] [blame] | 841 | |
Jiri Jaburek | 1f5eb34 | 2014-06-24 02:45:12 -0700 | [diff] [blame] | 842 | In case that that there are no unused loop devices, 'NULL' is returned. The |
Cyril Hrubis | 85e787e | 2014-06-18 17:09:21 +0200 | [diff] [blame] | 843 | test should skip the particular part of the test that needs the device with |
| 844 | 'TCONF'. |
| 845 | |
Jiri Jaburek | 1f5eb34 | 2014-06-24 02:45:12 -0700 | [diff] [blame] | 846 | WARNING: Because 'tst_acquire_device()' may create temporary file, you must |
Cyril Hrubis | 85e787e | 2014-06-18 17:09:21 +0200 | [diff] [blame] | 847 | call 'tst_tmpdir()' before you call 'tst_acquire_device()' |
| 848 | |
| 849 | [source,c] |
| 850 | ------------------------------------------------------------------------------- |
| 851 | #include "test.h" |
| 852 | |
| 853 | void tst_release_device(void (cleanup_fn)(void), const char *dev); |
| 854 | ------------------------------------------------------------------------------- |
| 855 | |
| 856 | Releases the device acquired by 'tst_acquire_device()'. |
| 857 | |
Xiaoguang Wang | 3e15bd7 | 2014-07-28 19:51:40 +0800 | [diff] [blame] | 858 | 2.2.15 Formatting a device with a filesystem |
Xiaoguang Wang | 3526685 | 2014-03-26 17:23:45 +0800 | [diff] [blame] | 859 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
| 860 | |
| 861 | [source,c] |
| 862 | ------------------------------------------------------------------------------- |
| 863 | #include "test.h" |
| 864 | |
Cyril Hrubis | e6c24c1 | 2014-06-19 12:46:45 +0200 | [diff] [blame] | 865 | const char *tst_dev_fs_type(void); |
| 866 | ------------------------------------------------------------------------------- |
| 867 | |
| 868 | Returns name of filesystem that should be used for tests. Unless is your test |
| 869 | designed to test specific filesystem you should use this function to select |
| 870 | filesystem for the 'tst_mkfs()'. |
| 871 | |
| 872 | NOTE: The default filesytem is hardcoded to 'ext2' in the sources and can be |
| 873 | overridden by setting 'LTP_DEV_FS_TYPE' environment variable. |
| 874 | |
| 875 | [source,c] |
| 876 | ------------------------------------------------------------------------------- |
| 877 | #include "test.h" |
| 878 | |
Xiaoguang Wang | 3526685 | 2014-03-26 17:23:45 +0800 | [diff] [blame] | 879 | void tst_mkfs(void (cleanup_fn)(void), const char *dev, |
| 880 | const char *fs_type, const char *const fs_opts[]); |
| 881 | ------------------------------------------------------------------------------- |
| 882 | |
| 883 | This function takes a path to a device, filesystem type and an array of extra |
| 884 | options passed to mkfs. |
| 885 | |
Jiri Jaburek | 1f5eb34 | 2014-06-24 02:45:12 -0700 | [diff] [blame] | 886 | The extra options 'fs_opts' should either be 'NULL' if there are none, or a |
Xiaoguang Wang | 3526685 | 2014-03-26 17:23:45 +0800 | [diff] [blame] | 887 | 'NULL' terminated array of strings such as '{"-b", "1024", NULL}'. |
| 888 | |
Xiaoguang Wang | 3e15bd7 | 2014-07-28 19:51:40 +0800 | [diff] [blame] | 889 | 2.2.16 Verifying a filesystem's free space |
Xiaoguang Wang | 4de5b2c | 2014-05-08 13:42:23 +0800 | [diff] [blame] | 890 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
| 891 | |
| 892 | Some tests have size requirements for the filesystem's free space. If these |
Jiri Jaburek | 1f5eb34 | 2014-06-24 02:45:12 -0700 | [diff] [blame] | 893 | requirements are not satisfied, the tests are not appropriate to run. |
Xiaoguang Wang | 4de5b2c | 2014-05-08 13:42:23 +0800 | [diff] [blame] | 894 | Especially when you run runltp with "-z" option to specify a big block device, |
| 895 | different tests have different requirements for the free space of this block |
| 896 | device. |
| 897 | |
| 898 | [source,c] |
| 899 | ------------------------------------------------------------------------------- |
| 900 | #include "test.h" |
| 901 | |
| 902 | int tst_fs_has_free(void (*cleanup)(void), const char *path, |
| 903 | unsigned int size, unsigned int mult); |
| 904 | ------------------------------------------------------------------------------- |
| 905 | |
| 906 | The 'tst_fs_has_free()' function returns 1 if there is enough space and 0 if |
| 907 | there is not. |
| 908 | |
Jiri Jaburek | 1f5eb34 | 2014-06-24 02:45:12 -0700 | [diff] [blame] | 909 | The 'path' is the pathname of any directory/file within a filesystem you want to |
| 910 | verify its free space of. |
Xiaoguang Wang | 4de5b2c | 2014-05-08 13:42:23 +0800 | [diff] [blame] | 911 | |
Jiri Jaburek | 1f5eb34 | 2014-06-24 02:45:12 -0700 | [diff] [blame] | 912 | The 'mult' is a multiplier, one of 'TST_BYTES', 'TST_KB', 'TST_MB' or 'TST_GB'. |
Xiaoguang Wang | 4de5b2c | 2014-05-08 13:42:23 +0800 | [diff] [blame] | 913 | |
| 914 | The required free space is calculated by 'size * mult', e.g. |
| 915 | 'tst_fs_has_free(cleanup, "/tmp/testfile", 64, TST_MB)' will return 1 if the |
| 916 | filesystem, which '"/tmp/testfile"' is in, has 64MB free space at least, and 0 |
| 917 | if not. |
| 918 | |
Xiaoguang Wang | 3e15bd7 | 2014-07-28 19:51:40 +0800 | [diff] [blame] | 919 | 2.2.17 Getting the maximum number of links to a regular file or directory |
Jiri Jaburek | 1f5eb34 | 2014-06-24 02:45:12 -0700 | [diff] [blame] | 920 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
Xiaoguang Wang | cee6cbe | 2014-06-18 14:31:03 +0800 | [diff] [blame] | 921 | |
Jiri Jaburek | 1f5eb34 | 2014-06-24 02:45:12 -0700 | [diff] [blame] | 922 | Some tests need to know the maximum count of links to a regular file or |
Xiaoguang Wang | cee6cbe | 2014-06-18 14:31:03 +0800 | [diff] [blame] | 923 | directory, such as 'rename(2)' or 'linkat(2)' to test 'EMLINK' error. |
| 924 | |
| 925 | [source,c] |
| 926 | ------------------------------------------------------------------------------- |
| 927 | #include "test.h" |
| 928 | |
| 929 | int tst_fs_fill_hardlinks(void (*cleanup)(void), const char *dir); |
| 930 | ------------------------------------------------------------------------------- |
| 931 | |
Jiri Jaburek | 1f5eb34 | 2014-06-24 02:45:12 -0700 | [diff] [blame] | 932 | Try to get maximum count of hard links to a regular file inside the 'dir'. |
Xiaoguang Wang | cee6cbe | 2014-06-18 14:31:03 +0800 | [diff] [blame] | 933 | |
| 934 | NOTE: This number depends on the filesystem 'dir' is on. |
| 935 | |
| 936 | This function uses 'link(2)' to create hard links to a single file until it |
Jiri Jaburek | 1f5eb34 | 2014-06-24 02:45:12 -0700 | [diff] [blame] | 937 | gets 'EMLINK' or creates 65535 links. If the limit is hit, the maximum number of |
Xiaoguang Wang | cee6cbe | 2014-06-18 14:31:03 +0800 | [diff] [blame] | 938 | hardlinks is returned and the 'dir' is filled with hardlinks in format |
Jiri Jaburek | 1f5eb34 | 2014-06-24 02:45:12 -0700 | [diff] [blame] | 939 | "testfile%i", where i belongs to [0, limit) interval. If no limit is hit or if |
Xiaoguang Wang | cee6cbe | 2014-06-18 14:31:03 +0800 | [diff] [blame] | 940 | 'link(2)' failed with 'ENOSPC' or 'EDQUOT', zero is returned and previously |
| 941 | created files are removed. |
| 942 | |
| 943 | [source,c] |
| 944 | ------------------------------------------------------------------------------- |
| 945 | #include "test.h" |
| 946 | |
| 947 | int tst_fs_fill_subdirs(void (*cleanup)(void), const char *dir); |
| 948 | ------------------------------------------------------------------------------- |
| 949 | |
| 950 | Try to get maximum number of subdirectories in directory. |
| 951 | |
Sheng Yong | 4584f91 | 2015-02-02 08:47:13 +0000 | [diff] [blame] | 952 | NOTE: This number depends on the filesystem 'dir' is on. For current kernel, |
| 953 | subdir limit is not availiable for all filesystems (availiable for ext2, ext3, |
| 954 | minix, sysv and more). If the test runs on some other filesystems, like ramfs, |
| 955 | tmpfs, it will not even try to reach the limit and return 0. |
Xiaoguang Wang | cee6cbe | 2014-06-18 14:31:03 +0800 | [diff] [blame] | 956 | |
| 957 | This function uses 'mkdir(2)' to create directories in 'dir' until it gets |
Jiri Jaburek | 1f5eb34 | 2014-06-24 02:45:12 -0700 | [diff] [blame] | 958 | 'EMLINK' or creates 65535 directories. If the limit is hit, the maximum number |
| 959 | of subdirectories is returned and the 'dir' is filled with subdirectories in |
| 960 | format "testdir%i", where i belongs to [0, limit - 2) interval (because each |
| 961 | newly created dir has two links already - the '.' and the link from parent |
| 962 | dir). If no limit is hit or if 'mkdir(2)' failed with 'ENOSPC' or 'EDQUOT', |
| 963 | zero is returned and previously created directories are removed. |
Xiaoguang Wang | cee6cbe | 2014-06-18 14:31:03 +0800 | [diff] [blame] | 964 | |
Xiaoguang Wang | 3e15bd7 | 2014-07-28 19:51:40 +0800 | [diff] [blame] | 965 | 2.2.18 Getting an unused PID number |
Stanislav Kholmanskikh | d2eb7d4 | 2014-07-03 11:24:42 +0400 | [diff] [blame] | 966 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
| 967 | |
| 968 | Some tests require a 'PID', which is not used by the OS (does not belong to |
| 969 | any process within it). For example, kill(2) should set errno to 'ESRCH' if |
| 970 | it's passed such 'PID'. |
| 971 | |
| 972 | [source,c] |
| 973 | ------------------------------------------------------------------------------- |
| 974 | #include "test.h" |
| 975 | |
| 976 | pid_t tst_get_unused_pid(void (*cleanup)(void)); |
| 977 | ------------------------------------------------------------------------------- |
| 978 | |
| 979 | Return a 'PID' value not used by the OS or any process within it. |
| 980 | |
Cyril Hrubis | 420add2 | 2015-01-29 16:00:10 +0100 | [diff] [blame] | 981 | 2.2.19 Umounting devices |
| 982 | ^^^^^^^^^^^^^^^^^^^^^^^^ |
| 983 | |
| 984 | [source,c] |
| 985 | ------------------------------------------------------------------------------- |
| 986 | #include "test.h" |
| 987 | |
| 988 | int tst_umount(const char *path); |
| 989 | ------------------------------------------------------------------------------- |
| 990 | |
| 991 | Since various desktop deamons (gvfsd-trash is known for that) may be stupid |
| 992 | enough to probe all newly mounted filesystem which results in 'umount(2)' |
| 993 | failing with 'EBUSY' LTP library includes 'tst_umount()' function that behaves |
| 994 | exactly as 'umount(2)' but retries several times on a failure. |
| 995 | |
| 996 | IMPORTANT: All testcases should use 'tst_umount()' instead of 'umount(2)' to |
| 997 | umount filesystems. |
| 998 | |
Stanislav Kholmanskikh | 571db51 | 2015-02-03 19:00:40 +0300 | [diff] [blame] | 999 | 2.2.20 Running executables |
| 1000 | ^^^^^^^^^^^^^^^^^^^^^^^^^^ |
| 1001 | |
| 1002 | [source,c] |
| 1003 | ------------------------------------------------------------------------------- |
| 1004 | #include "test.h" |
| 1005 | |
| 1006 | int tst_run_cmd(void (cleanup_fn)(void), |
| 1007 | const char *const argv[], |
| 1008 | const char *stdout_path, |
| 1009 | const char *stderr_path, |
| 1010 | int pass_exit_val); |
| 1011 | ------------------------------------------------------------------------------- |
| 1012 | |
| 1013 | 'tst_run_cmd' is a wrapper for 'vfork() + execvp()' which provides a way |
| 1014 | to execute an external program. |
| 1015 | |
| 1016 | 'argv[]' is a NULL-terminated array of strings starting with the program name |
| 1017 | which is followed by optional arguments. |
| 1018 | |
| 1019 | A non-zero 'pass_exit_val' makes 'tst_run_cmd' return the program exit code to |
| 1020 | the caller. A zero for 'pass_exit_val' makes 'tst_run_cmd' exit the tests |
| 1021 | on failure and call 'cleanup_fn' (if not NULL) beforehand. |
| 1022 | |
| 1023 | 'stdout_path' and 'stderr_path' determine where to redirect the program |
| 1024 | stdout and stderr I/O streams. |
| 1025 | |
| 1026 | .Example |
| 1027 | [source,c] |
| 1028 | ------------------------------------------------------------------------------- |
| 1029 | #include "test.h" |
| 1030 | |
| 1031 | const char *const cmd[] = { "ls", "-l", NULL }; |
| 1032 | |
| 1033 | ... |
| 1034 | /* Store output of 'ls -l' into log.txt */ |
| 1035 | tst_run_cmd(cleanup, cmd, "log.txt", NULL, 0); |
| 1036 | ... |
| 1037 | ------------------------------------------------------------------------------- |
| 1038 | |
Cyril Hrubis | 3346379 | 2014-03-12 17:13:30 +0100 | [diff] [blame] | 1039 | 2.3 Writing a testcase in shell |
| 1040 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 1041 | |
| 1042 | LTP supports testcases to be written in a portable shell too. |
| 1043 | |
| 1044 | There is a shell library modeled closely to the C interface (the source is |
| 1045 | located at 'testcases/lib/test.sh') and is installed to the same directory as |
| 1046 | the rest of the LTP test binaries. |
| 1047 | |
| 1048 | WARNING: All identifiers starting with TST_ or tst_ are reserved for the |
| 1049 | 'test.sh' library. |
| 1050 | |
| 1051 | 2.3.1 Basic shell test structure |
| 1052 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
| 1053 | |
| 1054 | [source,sh] |
| 1055 | ------------------------------------------------------------------------------- |
| 1056 | #!/bin/sh |
| 1057 | # |
| 1058 | # This is a basic test for true shell buildin |
| 1059 | # |
| 1060 | |
| 1061 | TCID=true01 |
| 1062 | TST_TOTAL=1 |
| 1063 | . test.sh |
| 1064 | |
| 1065 | true |
| 1066 | ret=$? |
| 1067 | |
| 1068 | if [ $ret -eq 0 ]; then |
| 1069 | tst_resm TPASS "true returned 0" |
| 1070 | else |
| 1071 | tst_resm TFAIL "true rturned $ret" |
| 1072 | fi |
| 1073 | |
| 1074 | tst_exit |
| 1075 | ------------------------------------------------------------------------------- |
| 1076 | |
| 1077 | TIP: To execute this test the 'test.sh' library must be in '$PATH'. If you are |
| 1078 | executing the test from a git checkout you can run it as |
| 1079 | 'PATH="$PATH:../../lib" ./foo01.sh' |
| 1080 | |
| 1081 | WARNING: Do not forget to add the 'tst_exit' at the end of the test, |
| 1082 | otherwise the test return value would be the return value of last |
| 1083 | executed command. |
| 1084 | |
| 1085 | 2.3.2 Basic test interface |
| 1086 | ^^^^^^^^^^^^^^^^^^^^^^^^^^ |
| 1087 | |
| 1088 | Following functions similar to the LTP C intearface are available. |
| 1089 | |
| 1090 | * tst_resm() |
| 1091 | * tst_brkm() |
| 1092 | * tst_exit() |
| 1093 | * tst_require_root() |
| 1094 | * tst_tmpdir() |
| 1095 | * tst_rmdir() |
Xiaoguang Wang | 4de5b2c | 2014-05-08 13:42:23 +0800 | [diff] [blame] | 1096 | * tst_fs_has_free() |
Cyril Hrubis | 3346379 | 2014-03-12 17:13:30 +0100 | [diff] [blame] | 1097 | |
| 1098 | There is one more function called 'tst_check_cmds()' that gets unspecified |
| 1099 | number of parameters and asserts that each parameter is a name of an |
| 1100 | executable in '$PATH' and exits the test with 'TCONF' on first missing. |
| 1101 | |
Xiaoguang Wang | 4de5b2c | 2014-05-08 13:42:23 +0800 | [diff] [blame] | 1102 | .tst_fs_has_free |
| 1103 | [source,sh] |
| 1104 | ------------------------------------------------------------------------------- |
| 1105 | #!/bin/sh |
| 1106 | |
| 1107 | ... |
| 1108 | |
| 1109 | # whether current directory has 100MB free space at least. |
| 1110 | if ! tst_fs_has_free . 100MB; then |
| 1111 | tst_brkm TCONF "Not enough free space" |
| 1112 | fi |
| 1113 | |
| 1114 | ... |
| 1115 | ------------------------------------------------------------------------------- |
| 1116 | |
| 1117 | The tst_fs_has_free shell interface returns 0 if the specified free space is |
| 1118 | satisfied, 1 if not, and 2 on error. |
| 1119 | |
| 1120 | The second argument supports suffixes kB, MB and GB, the default unit is Byte. |
| 1121 | |
Cyril Hrubis | 3346379 | 2014-03-12 17:13:30 +0100 | [diff] [blame] | 1122 | 2.3.3 Cleanup |
| 1123 | ^^^^^^^^^^^^^ |
| 1124 | |
Jiri Jaburek | 1f5eb34 | 2014-06-24 02:45:12 -0700 | [diff] [blame] | 1125 | Due to differences between C and shell, the cleanup callback is done using a |
Cyril Hrubis | 3346379 | 2014-03-12 17:13:30 +0100 | [diff] [blame] | 1126 | 'TST_CLEANUP' shell variable that, if not empty, is evaluated before the test |
| 1127 | exits (either after calling 'tst_exit()' or 'tst_brkm()'). See example below. |
| 1128 | |
| 1129 | [source,sh] |
| 1130 | ------------------------------------------------------------------------------- |
| 1131 | #!/bin/sh |
| 1132 | # |
| 1133 | # Test cleanup example |
| 1134 | # |
| 1135 | |
| 1136 | TCID=true01 |
| 1137 | TST_TOTAL=1 |
| 1138 | . test.sh |
| 1139 | |
| 1140 | cleanup() |
| 1141 | { |
| 1142 | tst_rmdir |
| 1143 | } |
| 1144 | |
| 1145 | tst_tmpdir |
| 1146 | TST_CLEANUP=cleanup |
| 1147 | |
| 1148 | # Do the test here |
| 1149 | |
| 1150 | tst_exit |
| 1151 | ------------------------------------------------------------------------------- |
| 1152 | |
Cyril Hrubis | 7904074 | 2014-03-26 13:51:38 +0100 | [diff] [blame] | 1153 | 2.3.4 Restarting daemons |
| 1154 | ^^^^^^^^^^^^^^^^^^^^^^^^ |
| 1155 | |
| 1156 | Restarting system daemons is a complicated task for two reasons. |
| 1157 | |
| 1158 | * There are different init systems |
| 1159 | (SysV init, systemd, etc...) |
| 1160 | |
| 1161 | * Daemon names are not unified between distributions |
| 1162 | (apache vs httpd, cron vs crond, various syslog variations) |
| 1163 | |
| 1164 | To solve these problems LTP has 'testcases/lib/daemonlib.sh' library that |
| 1165 | provides functions to start/stop/query daemons as well as variables that store |
| 1166 | correct daemon name. |
| 1167 | |
| 1168 | .Supported operations |
| 1169 | |============================================================================== |
| 1170 | | start_daemon() | Starts daemon, name is passed as first parameter. |
| 1171 | | stop_daemon() | Stops daemon, name is passed as first parameter. |
| 1172 | | restart_daemon() | Restarts daemon, name is passed as first parameter. |
| 1173 | | status_daemon() | Returns daemon status, TODO: what is return value? |
| 1174 | |============================================================================== |
| 1175 | |
| 1176 | .Variables with detected names |
| 1177 | |============================================================================== |
| 1178 | | CROND_DAEMON | Cron daemon name (cron, crond). |
| 1179 | | SYSLOG_DAEMON | Syslog daemon name (syslog, syslog-ng, rsyslog). |
| 1180 | |============================================================================== |
| 1181 | |
| 1182 | .Cron daemon restart example |
| 1183 | [source,sh] |
| 1184 | ------------------------------------------------------------------------------- |
| 1185 | #!/bin/sh |
| 1186 | # |
| 1187 | # Cron daemon restart example |
| 1188 | # |
| 1189 | TCID=cron01 |
| 1190 | TST_COUNT=1 |
| 1191 | . test.sh |
| 1192 | . daemonlib.sh |
| 1193 | |
| 1194 | ... |
| 1195 | |
| 1196 | restart_daemon $CROND_DAEMON |
| 1197 | |
| 1198 | ... |
| 1199 | |
| 1200 | tst_exit |
| 1201 | ------------------------------------------------------------------------------- |
| 1202 | |
Cyril Hrubis | eb44f8e | 2014-03-13 14:42:16 +0100 | [diff] [blame] | 1203 | |
| 1204 | 3. Common problems |
| 1205 | ------------------ |
| 1206 | |
Jiri Jaburek | 1f5eb34 | 2014-06-24 02:45:12 -0700 | [diff] [blame] | 1207 | This chapter describes common problems/misuses and less obvious design patters |
Cyril Hrubis | eb44f8e | 2014-03-13 14:42:16 +0100 | [diff] [blame] | 1208 | (quirks) in UNIX interfaces. Read it carefully :) |
| 1209 | |
| 1210 | 3.1 umask() |
| 1211 | ~~~~~~~~~~~ |
| 1212 | |
Jiri Jaburek | 1f5eb34 | 2014-06-24 02:45:12 -0700 | [diff] [blame] | 1213 | I've been hit by this one several times already... When you create files |
Cyril Hrubis | eb44f8e | 2014-03-13 14:42:16 +0100 | [diff] [blame] | 1214 | with 'open()' or 'creat()' etc, the mode specified as the last parameter *is |
| 1215 | not* the mode the file is created with. The mode depends on current 'umask()' |
| 1216 | settings which may clear some of the bits. If your test depends on specific |
Cyril Hrubis | 2197743 | 2014-05-29 18:47:03 +0200 | [diff] [blame] | 1217 | file permissions you need either to change umask to 0 or 'chmod()' the file |
| 1218 | afterwards or use SAFE_TOUCH() that does the 'chmod()' for you. |
Cyril Hrubis | eb44f8e | 2014-03-13 14:42:16 +0100 | [diff] [blame] | 1219 | |
Alexey Kodanev | fb3da0a | 2014-05-13 15:34:32 +0400 | [diff] [blame] | 1220 | 3.2 access() |
| 1221 | ~~~~~~~~~~~ |
| 1222 | |
Jiri Jaburek | 1f5eb34 | 2014-06-24 02:45:12 -0700 | [diff] [blame] | 1223 | If 'access(some_file, W_OK)' is executed by root, it will return success even |
Alexey Kodanev | fb3da0a | 2014-05-13 15:34:32 +0400 | [diff] [blame] | 1224 | if the file doesn't have write permission bits set (the same holds for R_OK |
Jiri Jaburek | 1f5eb34 | 2014-06-24 02:45:12 -0700 | [diff] [blame] | 1225 | too). For sysfs files you can use 'open()' as a workaround to check file |
Alexey Kodanev | fb3da0a | 2014-05-13 15:34:32 +0400 | [diff] [blame] | 1226 | read/write permissions. It might not work for other filesystems, for these you |
| 1227 | have to use 'stat()', 'lstat()' or 'fstat()'. |
Cyril Hrubis | eb44f8e | 2014-03-13 14:42:16 +0100 | [diff] [blame] | 1228 | |
Cyril Hrubis | 420add2 | 2015-01-29 16:00:10 +0100 | [diff] [blame] | 1229 | 3.3 umount() EBUSY |
| 1230 | ~~~~~~~~~~~~~~~~~~ |
| 1231 | |
| 1232 | Various desktop deamons (gvfsd-trash is known for that) may be stupid enough |
| 1233 | to probe all newly mounted filesystem which results in 'umount(2)' failing |
| 1234 | with 'EBUSY'; use 'tst_umount()' described in 2.2.19 that retries in this case |
| 1235 | instead of plain 'umount(2)'. |
| 1236 | |
| 1237 | |
Cyril Hrubis | eb44f8e | 2014-03-13 14:42:16 +0100 | [diff] [blame] | 1238 | 4. Test Contribution Checklist |
Cyril Hrubis | afb6168 | 2014-01-13 19:08:02 +0100 | [diff] [blame] | 1239 | ------------------------------ |
| 1240 | |
| 1241 | 1. Test compiles and runs fine (check with -i 10 too) |
| 1242 | 2. Checkpatch does not report any errors |
| 1243 | 3. The runtest entires are in place |
| 1244 | 4. Test files are added into corresponding .gitignore files |
| 1245 | 5. Patches apply over the latest git |
Cyril Hrubis | eb44f8e | 2014-03-13 14:42:16 +0100 | [diff] [blame] | 1246 | |
| 1247 | |
| 1248 | 4.1 About .gitignore files |
| 1249 | ~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 1250 | |
| 1251 | There are numerous '.gitignore' files in the LTP tree. Usually there is a |
| 1252 | '.gitignore' file per a group of tests. The reason for this setup is simple. |
Jiri Jaburek | 1f5eb34 | 2014-06-24 02:45:12 -0700 | [diff] [blame] | 1253 | It's easier to maintain a '.gitignore' file per directory with tests, rather |
| 1254 | than having single file in the project root directory. This way, we don't have |
| 1255 | to update all the gitignore files when moving directories, and they get deleted |
| 1256 | automatically when a directory with tests is removed. |