Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

selftests/clone3: Report descriptive test names

The clone3() selftests currently report test results in a format that does
not mesh entirely well with automation. They log output for each test such
as:

# [1382411] Trying clone3() with flags 0 (size 0)
# I am the parent (1382411). My child's pid is 1382412
# I am the child, my PID is 1382412
# [1382411] clone3() with flags says: 0 expected 0
ok 1 [1382411] Result (0) matches expectation (0)

This is not ideal for automated parsers since the text after the "ok 1" is
treated as the test name when comparing runs by a lot of automation (tests
routinely get renumbered due to things like new tests being added based on
logical groupings). The PID means that the test names will frequently vary
and the rest of the name being a description of results means several tests
have identical text there.

Address this by refactoring things so that we have a static descriptive
name for each test which we use when logging passes, failures and skips
and since we now have a stable name for the test to hand log that before
starting the test to address the common issue reading logs where the test
name is only printed after any diagnostics. The result is:

# Running test 'simple clone3()'
# [1562777] Trying clone3() with flags 0 (size 0)
# I am the parent (1562777). My child's pid is 1562778
# I am the child, my PID is 1562778
# [1562777] clone3() with flags says: 0 expected 0
ok 1 simple clone3()

In order to handle skips a bit more neatly this is done in a moderately
invasive fashion where we move from a sequence of function calls to having
an array of test parameters. This hopefully also makes it a little easier
to see what the tests are doing when looking at both the source and the
logs.

Signed-off-by: Mark Brown <broonie@kernel.org>
Signed-off-by: Shuah Khan <skhan@linuxfoundation.org>

authored by

Mark Brown and committed by
Shuah Khan
34dce23f ecc4185a

+194 -75
+194 -75
tools/testing/selftests/clone3/clone3.c
··· 7 7 #include <inttypes.h> 8 8 #include <linux/types.h> 9 9 #include <linux/sched.h> 10 + #include <stdbool.h> 10 11 #include <stdint.h> 11 12 #include <stdio.h> 12 13 #include <stdlib.h> ··· 104 103 return 0; 105 104 } 106 105 107 - static void test_clone3(uint64_t flags, size_t size, int expected, 108 - enum test_mode test_mode) 106 + static bool test_clone3(uint64_t flags, size_t size, int expected, 107 + enum test_mode test_mode) 109 108 { 110 109 int ret; 111 110 ··· 115 114 ret = call_clone3(flags, size, test_mode); 116 115 ksft_print_msg("[%d] clone3() with flags says: %d expected %d\n", 117 116 getpid(), ret, expected); 118 - if (ret != expected) 119 - ksft_test_result_fail( 117 + if (ret != expected) { 118 + ksft_print_msg( 120 119 "[%d] Result (%d) is different than expected (%d)\n", 121 120 getpid(), ret, expected); 122 - else 123 - ksft_test_result_pass( 124 - "[%d] Result (%d) matches expectation (%d)\n", 125 - getpid(), ret, expected); 121 + return false; 122 + } 123 + 124 + return true; 126 125 } 126 + 127 + typedef bool (*filter_function)(void); 128 + typedef size_t (*size_function)(void); 129 + 130 + static bool not_root(void) 131 + { 132 + if (getuid() != 0) { 133 + ksft_print_msg("Not running as root\n"); 134 + return true; 135 + } 136 + 137 + return false; 138 + } 139 + 140 + static size_t page_size_plus_8(void) 141 + { 142 + return getpagesize() + 8; 143 + } 144 + 145 + struct test { 146 + const char *name; 147 + uint64_t flags; 148 + size_t size; 149 + size_function size_function; 150 + int expected; 151 + enum test_mode test_mode; 152 + filter_function filter; 153 + }; 154 + 155 + static const struct test tests[] = { 156 + { 157 + .name = "simple clone3()", 158 + .flags = 0, 159 + .size = 0, 160 + .expected = 0, 161 + .test_mode = CLONE3_ARGS_NO_TEST, 162 + }, 163 + { 164 + .name = "clone3() in a new PID_NS", 165 + .flags = CLONE_NEWPID, 166 + .size = 0, 167 + .expected = 0, 168 + .test_mode = CLONE3_ARGS_NO_TEST, 169 + .filter = not_root, 170 + }, 171 + { 172 + .name = "CLONE_ARGS_SIZE_VER0", 173 + .flags = 0, 174 + .size = CLONE_ARGS_SIZE_VER0, 175 + .expected = 0, 176 + .test_mode = CLONE3_ARGS_NO_TEST, 177 + }, 178 + { 179 + .name = "CLONE_ARGS_SIZE_VER0 - 8", 180 + .flags = 0, 181 + .size = CLONE_ARGS_SIZE_VER0 - 8, 182 + .expected = -EINVAL, 183 + .test_mode = CLONE3_ARGS_NO_TEST, 184 + }, 185 + { 186 + .name = "sizeof(struct clone_args) + 8", 187 + .flags = 0, 188 + .size = sizeof(struct __clone_args) + 8, 189 + .expected = 0, 190 + .test_mode = CLONE3_ARGS_NO_TEST, 191 + }, 192 + { 193 + .name = "exit_signal with highest 32 bits non-zero", 194 + .flags = 0, 195 + .size = 0, 196 + .expected = -EINVAL, 197 + .test_mode = CLONE3_ARGS_INVAL_EXIT_SIGNAL_BIG, 198 + }, 199 + { 200 + .name = "negative 32-bit exit_signal", 201 + .flags = 0, 202 + .size = 0, 203 + .expected = -EINVAL, 204 + .test_mode = CLONE3_ARGS_INVAL_EXIT_SIGNAL_NEG, 205 + }, 206 + { 207 + .name = "exit_signal not fitting into CSIGNAL mask", 208 + .flags = 0, 209 + .size = 0, 210 + .expected = -EINVAL, 211 + .test_mode = CLONE3_ARGS_INVAL_EXIT_SIGNAL_CSIG, 212 + }, 213 + { 214 + .name = "NSIG < exit_signal < CSIG", 215 + .flags = 0, 216 + .size = 0, 217 + .expected = -EINVAL, 218 + .test_mode = CLONE3_ARGS_INVAL_EXIT_SIGNAL_NSIG, 219 + }, 220 + { 221 + .name = "Arguments sizeof(struct clone_args) + 8", 222 + .flags = 0, 223 + .size = sizeof(struct __clone_args) + 8, 224 + .expected = 0, 225 + .test_mode = CLONE3_ARGS_ALL_0, 226 + }, 227 + { 228 + .name = "Arguments sizeof(struct clone_args) + 16", 229 + .flags = 0, 230 + .size = sizeof(struct __clone_args) + 16, 231 + .expected = -E2BIG, 232 + .test_mode = CLONE3_ARGS_ALL_0, 233 + }, 234 + { 235 + .name = "Arguments sizeof(struct clone_arg) * 2", 236 + .flags = 0, 237 + .size = sizeof(struct __clone_args) + 16, 238 + .expected = -E2BIG, 239 + .test_mode = CLONE3_ARGS_ALL_0, 240 + }, 241 + { 242 + .name = "Arguments > page size", 243 + .flags = 0, 244 + .size_function = page_size_plus_8, 245 + .expected = -E2BIG, 246 + .test_mode = CLONE3_ARGS_NO_TEST, 247 + }, 248 + { 249 + .name = "CLONE_ARGS_SIZE_VER0 in a new PID NS", 250 + .flags = CLONE_NEWPID, 251 + .size = CLONE_ARGS_SIZE_VER0, 252 + .expected = 0, 253 + .test_mode = CLONE3_ARGS_NO_TEST, 254 + .filter = not_root, 255 + }, 256 + { 257 + .name = "CLONE_ARGS_SIZE_VER0 - 8 in a new PID NS", 258 + .flags = CLONE_NEWPID, 259 + .size = CLONE_ARGS_SIZE_VER0 - 8, 260 + .expected = -EINVAL, 261 + .test_mode = CLONE3_ARGS_NO_TEST, 262 + }, 263 + { 264 + .name = "sizeof(struct clone_args) + 8 in a new PID NS", 265 + .flags = CLONE_NEWPID, 266 + .size = sizeof(struct __clone_args) + 8, 267 + .expected = 0, 268 + .test_mode = CLONE3_ARGS_NO_TEST, 269 + .filter = not_root, 270 + }, 271 + { 272 + .name = "Arguments > page size in a new PID NS", 273 + .flags = CLONE_NEWPID, 274 + .size_function = page_size_plus_8, 275 + .expected = -E2BIG, 276 + .test_mode = CLONE3_ARGS_NO_TEST, 277 + }, 278 + { 279 + .name = "New time NS", 280 + .flags = CLONE_NEWTIME, 281 + .size = 0, 282 + .expected = 0, 283 + .test_mode = CLONE3_ARGS_NO_TEST, 284 + }, 285 + { 286 + .name = "exit signal (SIGCHLD) in flags", 287 + .flags = SIGCHLD, 288 + .size = 0, 289 + .expected = -EINVAL, 290 + .test_mode = CLONE3_ARGS_NO_TEST, 291 + }, 292 + }; 127 293 128 294 int main(int argc, char *argv[]) 129 295 { 130 - uid_t uid = getuid(); 296 + size_t size; 297 + int i; 131 298 132 299 ksft_print_header(); 133 - ksft_set_plan(19); 300 + ksft_set_plan(ARRAY_SIZE(tests)); 134 301 test_clone3_supported(); 135 302 136 - /* Just a simple clone3() should return 0.*/ 137 - test_clone3(0, 0, 0, CLONE3_ARGS_NO_TEST); 303 + for (i = 0; i < ARRAY_SIZE(tests); i++) { 304 + if (tests[i].filter && tests[i].filter()) { 305 + ksft_test_result_skip("%s\n", tests[i].name); 306 + continue; 307 + } 138 308 139 - /* Do a clone3() in a new PID NS.*/ 140 - if (uid == 0) 141 - test_clone3(CLONE_NEWPID, 0, 0, CLONE3_ARGS_NO_TEST); 142 - else 143 - ksft_test_result_skip("Skipping clone3() with CLONE_NEWPID\n"); 309 + if (tests[i].size_function) 310 + size = tests[i].size_function(); 311 + else 312 + size = tests[i].size; 144 313 145 - /* Do a clone3() with CLONE_ARGS_SIZE_VER0. */ 146 - test_clone3(0, CLONE_ARGS_SIZE_VER0, 0, CLONE3_ARGS_NO_TEST); 314 + ksft_print_msg("Running test '%s'\n", tests[i].name); 147 315 148 - /* Do a clone3() with CLONE_ARGS_SIZE_VER0 - 8 */ 149 - test_clone3(0, CLONE_ARGS_SIZE_VER0 - 8, -EINVAL, CLONE3_ARGS_NO_TEST); 150 - 151 - /* Do a clone3() with sizeof(struct clone_args) + 8 */ 152 - test_clone3(0, sizeof(struct __clone_args) + 8, 0, CLONE3_ARGS_NO_TEST); 153 - 154 - /* Do a clone3() with exit_signal having highest 32 bits non-zero */ 155 - test_clone3(0, 0, -EINVAL, CLONE3_ARGS_INVAL_EXIT_SIGNAL_BIG); 156 - 157 - /* Do a clone3() with negative 32-bit exit_signal */ 158 - test_clone3(0, 0, -EINVAL, CLONE3_ARGS_INVAL_EXIT_SIGNAL_NEG); 159 - 160 - /* Do a clone3() with exit_signal not fitting into CSIGNAL mask */ 161 - test_clone3(0, 0, -EINVAL, CLONE3_ARGS_INVAL_EXIT_SIGNAL_CSIG); 162 - 163 - /* Do a clone3() with NSIG < exit_signal < CSIG */ 164 - test_clone3(0, 0, -EINVAL, CLONE3_ARGS_INVAL_EXIT_SIGNAL_NSIG); 165 - 166 - test_clone3(0, sizeof(struct __clone_args) + 8, 0, CLONE3_ARGS_ALL_0); 167 - 168 - test_clone3(0, sizeof(struct __clone_args) + 16, -E2BIG, 169 - CLONE3_ARGS_ALL_0); 170 - 171 - test_clone3(0, sizeof(struct __clone_args) * 2, -E2BIG, 172 - CLONE3_ARGS_ALL_0); 173 - 174 - /* Do a clone3() with > page size */ 175 - test_clone3(0, getpagesize() + 8, -E2BIG, CLONE3_ARGS_NO_TEST); 176 - 177 - /* Do a clone3() with CLONE_ARGS_SIZE_VER0 in a new PID NS. */ 178 - if (uid == 0) 179 - test_clone3(CLONE_NEWPID, CLONE_ARGS_SIZE_VER0, 0, 180 - CLONE3_ARGS_NO_TEST); 181 - else 182 - ksft_test_result_skip("Skipping clone3() with CLONE_NEWPID\n"); 183 - 184 - /* Do a clone3() with CLONE_ARGS_SIZE_VER0 - 8 in a new PID NS */ 185 - test_clone3(CLONE_NEWPID, CLONE_ARGS_SIZE_VER0 - 8, -EINVAL, 186 - CLONE3_ARGS_NO_TEST); 187 - 188 - /* Do a clone3() with sizeof(struct clone_args) + 8 in a new PID NS */ 189 - if (uid == 0) 190 - test_clone3(CLONE_NEWPID, sizeof(struct __clone_args) + 8, 0, 191 - CLONE3_ARGS_NO_TEST); 192 - else 193 - ksft_test_result_skip("Skipping clone3() with CLONE_NEWPID\n"); 194 - 195 - /* Do a clone3() with > page size in a new PID NS */ 196 - test_clone3(CLONE_NEWPID, getpagesize() + 8, -E2BIG, 197 - CLONE3_ARGS_NO_TEST); 198 - 199 - /* Do a clone3() in a new time namespace */ 200 - test_clone3(CLONE_NEWTIME, 0, 0, CLONE3_ARGS_NO_TEST); 201 - 202 - /* Do a clone3() with exit signal (SIGCHLD) in flags */ 203 - test_clone3(SIGCHLD, 0, -EINVAL, CLONE3_ARGS_NO_TEST); 316 + ksft_test_result(test_clone3(tests[i].flags, size, 317 + tests[i].expected, 318 + tests[i].test_mode), 319 + "%s\n", tests[i].name); 320 + } 204 321 205 322 ksft_finished(); 206 323 }