Skip to content

Commit 34dce23

Browse files
broonieshuahkh
authored andcommitted
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>
1 parent ecc4185 commit 34dce23

File tree

1 file changed

+192
-73
lines changed

1 file changed

+192
-73
lines changed

tools/testing/selftests/clone3/clone3.c

Lines changed: 192 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include <inttypes.h>
88
#include <linux/types.h>
99
#include <linux/sched.h>
10+
#include <stdbool.h>
1011
#include <stdint.h>
1112
#include <stdio.h>
1213
#include <stdlib.h>
@@ -103,8 +104,8 @@ static int call_clone3(uint64_t flags, size_t size, enum test_mode test_mode)
103104
return 0;
104105
}
105106

106-
static void test_clone3(uint64_t flags, size_t size, int expected,
107-
enum test_mode test_mode)
107+
static bool test_clone3(uint64_t flags, size_t size, int expected,
108+
enum test_mode test_mode)
108109
{
109110
int ret;
110111

@@ -114,92 +115,210 @@ static void test_clone3(uint64_t flags, size_t size, int expected,
114115
ret = call_clone3(flags, size, test_mode);
115116
ksft_print_msg("[%d] clone3() with flags says: %d expected %d\n",
116117
getpid(), ret, expected);
117-
if (ret != expected)
118-
ksft_test_result_fail(
118+
if (ret != expected) {
119+
ksft_print_msg(
119120
"[%d] Result (%d) is different than expected (%d)\n",
120121
getpid(), ret, expected);
121-
else
122-
ksft_test_result_pass(
123-
"[%d] Result (%d) matches expectation (%d)\n",
124-
getpid(), ret, expected);
125-
}
126-
127-
int main(int argc, char *argv[])
128-
{
129-
uid_t uid = getuid();
130-
131-
ksft_print_header();
132-
ksft_set_plan(19);
133-
test_clone3_supported();
134-
135-
/* Just a simple clone3() should return 0.*/
136-
test_clone3(0, 0, 0, CLONE3_ARGS_NO_TEST);
137-
138-
/* Do a clone3() in a new PID NS.*/
139-
if (uid == 0)
140-
test_clone3(CLONE_NEWPID, 0, 0, CLONE3_ARGS_NO_TEST);
141-
else
142-
ksft_test_result_skip("Skipping clone3() with CLONE_NEWPID\n");
143-
144-
/* Do a clone3() with CLONE_ARGS_SIZE_VER0. */
145-
test_clone3(0, CLONE_ARGS_SIZE_VER0, 0, CLONE3_ARGS_NO_TEST);
146-
147-
/* Do a clone3() with CLONE_ARGS_SIZE_VER0 - 8 */
148-
test_clone3(0, CLONE_ARGS_SIZE_VER0 - 8, -EINVAL, CLONE3_ARGS_NO_TEST);
149-
150-
/* Do a clone3() with sizeof(struct clone_args) + 8 */
151-
test_clone3(0, sizeof(struct __clone_args) + 8, 0, CLONE3_ARGS_NO_TEST);
152-
153-
/* Do a clone3() with exit_signal having highest 32 bits non-zero */
154-
test_clone3(0, 0, -EINVAL, CLONE3_ARGS_INVAL_EXIT_SIGNAL_BIG);
122+
return false;
123+
}
155124

156-
/* Do a clone3() with negative 32-bit exit_signal */
157-
test_clone3(0, 0, -EINVAL, CLONE3_ARGS_INVAL_EXIT_SIGNAL_NEG);
125+
return true;
126+
}
158127

159-
/* Do a clone3() with exit_signal not fitting into CSIGNAL mask */
160-
test_clone3(0, 0, -EINVAL, CLONE3_ARGS_INVAL_EXIT_SIGNAL_CSIG);
128+
typedef bool (*filter_function)(void);
129+
typedef size_t (*size_function)(void);
161130

162-
/* Do a clone3() with NSIG < exit_signal < CSIG */
163-
test_clone3(0, 0, -EINVAL, CLONE3_ARGS_INVAL_EXIT_SIGNAL_NSIG);
131+
static bool not_root(void)
132+
{
133+
if (getuid() != 0) {
134+
ksft_print_msg("Not running as root\n");
135+
return true;
136+
}
164137

165-
test_clone3(0, sizeof(struct __clone_args) + 8, 0, CLONE3_ARGS_ALL_0);
138+
return false;
139+
}
166140

167-
test_clone3(0, sizeof(struct __clone_args) + 16, -E2BIG,
168-
CLONE3_ARGS_ALL_0);
141+
static size_t page_size_plus_8(void)
142+
{
143+
return getpagesize() + 8;
144+
}
169145

170-
test_clone3(0, sizeof(struct __clone_args) * 2, -E2BIG,
171-
CLONE3_ARGS_ALL_0);
146+
struct test {
147+
const char *name;
148+
uint64_t flags;
149+
size_t size;
150+
size_function size_function;
151+
int expected;
152+
enum test_mode test_mode;
153+
filter_function filter;
154+
};
172155

173-
/* Do a clone3() with > page size */
174-
test_clone3(0, getpagesize() + 8, -E2BIG, CLONE3_ARGS_NO_TEST);
156+
static const struct test tests[] = {
157+
{
158+
.name = "simple clone3()",
159+
.flags = 0,
160+
.size = 0,
161+
.expected = 0,
162+
.test_mode = CLONE3_ARGS_NO_TEST,
163+
},
164+
{
165+
.name = "clone3() in a new PID_NS",
166+
.flags = CLONE_NEWPID,
167+
.size = 0,
168+
.expected = 0,
169+
.test_mode = CLONE3_ARGS_NO_TEST,
170+
.filter = not_root,
171+
},
172+
{
173+
.name = "CLONE_ARGS_SIZE_VER0",
174+
.flags = 0,
175+
.size = CLONE_ARGS_SIZE_VER0,
176+
.expected = 0,
177+
.test_mode = CLONE3_ARGS_NO_TEST,
178+
},
179+
{
180+
.name = "CLONE_ARGS_SIZE_VER0 - 8",
181+
.flags = 0,
182+
.size = CLONE_ARGS_SIZE_VER0 - 8,
183+
.expected = -EINVAL,
184+
.test_mode = CLONE3_ARGS_NO_TEST,
185+
},
186+
{
187+
.name = "sizeof(struct clone_args) + 8",
188+
.flags = 0,
189+
.size = sizeof(struct __clone_args) + 8,
190+
.expected = 0,
191+
.test_mode = CLONE3_ARGS_NO_TEST,
192+
},
193+
{
194+
.name = "exit_signal with highest 32 bits non-zero",
195+
.flags = 0,
196+
.size = 0,
197+
.expected = -EINVAL,
198+
.test_mode = CLONE3_ARGS_INVAL_EXIT_SIGNAL_BIG,
199+
},
200+
{
201+
.name = "negative 32-bit exit_signal",
202+
.flags = 0,
203+
.size = 0,
204+
.expected = -EINVAL,
205+
.test_mode = CLONE3_ARGS_INVAL_EXIT_SIGNAL_NEG,
206+
},
207+
{
208+
.name = "exit_signal not fitting into CSIGNAL mask",
209+
.flags = 0,
210+
.size = 0,
211+
.expected = -EINVAL,
212+
.test_mode = CLONE3_ARGS_INVAL_EXIT_SIGNAL_CSIG,
213+
},
214+
{
215+
.name = "NSIG < exit_signal < CSIG",
216+
.flags = 0,
217+
.size = 0,
218+
.expected = -EINVAL,
219+
.test_mode = CLONE3_ARGS_INVAL_EXIT_SIGNAL_NSIG,
220+
},
221+
{
222+
.name = "Arguments sizeof(struct clone_args) + 8",
223+
.flags = 0,
224+
.size = sizeof(struct __clone_args) + 8,
225+
.expected = 0,
226+
.test_mode = CLONE3_ARGS_ALL_0,
227+
},
228+
{
229+
.name = "Arguments sizeof(struct clone_args) + 16",
230+
.flags = 0,
231+
.size = sizeof(struct __clone_args) + 16,
232+
.expected = -E2BIG,
233+
.test_mode = CLONE3_ARGS_ALL_0,
234+
},
235+
{
236+
.name = "Arguments sizeof(struct clone_arg) * 2",
237+
.flags = 0,
238+
.size = sizeof(struct __clone_args) + 16,
239+
.expected = -E2BIG,
240+
.test_mode = CLONE3_ARGS_ALL_0,
241+
},
242+
{
243+
.name = "Arguments > page size",
244+
.flags = 0,
245+
.size_function = page_size_plus_8,
246+
.expected = -E2BIG,
247+
.test_mode = CLONE3_ARGS_NO_TEST,
248+
},
249+
{
250+
.name = "CLONE_ARGS_SIZE_VER0 in a new PID NS",
251+
.flags = CLONE_NEWPID,
252+
.size = CLONE_ARGS_SIZE_VER0,
253+
.expected = 0,
254+
.test_mode = CLONE3_ARGS_NO_TEST,
255+
.filter = not_root,
256+
},
257+
{
258+
.name = "CLONE_ARGS_SIZE_VER0 - 8 in a new PID NS",
259+
.flags = CLONE_NEWPID,
260+
.size = CLONE_ARGS_SIZE_VER0 - 8,
261+
.expected = -EINVAL,
262+
.test_mode = CLONE3_ARGS_NO_TEST,
263+
},
264+
{
265+
.name = "sizeof(struct clone_args) + 8 in a new PID NS",
266+
.flags = CLONE_NEWPID,
267+
.size = sizeof(struct __clone_args) + 8,
268+
.expected = 0,
269+
.test_mode = CLONE3_ARGS_NO_TEST,
270+
.filter = not_root,
271+
},
272+
{
273+
.name = "Arguments > page size in a new PID NS",
274+
.flags = CLONE_NEWPID,
275+
.size_function = page_size_plus_8,
276+
.expected = -E2BIG,
277+
.test_mode = CLONE3_ARGS_NO_TEST,
278+
},
279+
{
280+
.name = "New time NS",
281+
.flags = CLONE_NEWTIME,
282+
.size = 0,
283+
.expected = 0,
284+
.test_mode = CLONE3_ARGS_NO_TEST,
285+
},
286+
{
287+
.name = "exit signal (SIGCHLD) in flags",
288+
.flags = SIGCHLD,
289+
.size = 0,
290+
.expected = -EINVAL,
291+
.test_mode = CLONE3_ARGS_NO_TEST,
292+
},
293+
};
175294

176-
/* Do a clone3() with CLONE_ARGS_SIZE_VER0 in a new PID NS. */
177-
if (uid == 0)
178-
test_clone3(CLONE_NEWPID, CLONE_ARGS_SIZE_VER0, 0,
179-
CLONE3_ARGS_NO_TEST);
180-
else
181-
ksft_test_result_skip("Skipping clone3() with CLONE_NEWPID\n");
295+
int main(int argc, char *argv[])
296+
{
297+
size_t size;
298+
int i;
182299

183-
/* Do a clone3() with CLONE_ARGS_SIZE_VER0 - 8 in a new PID NS */
184-
test_clone3(CLONE_NEWPID, CLONE_ARGS_SIZE_VER0 - 8, -EINVAL,
185-
CLONE3_ARGS_NO_TEST);
300+
ksft_print_header();
301+
ksft_set_plan(ARRAY_SIZE(tests));
302+
test_clone3_supported();
186303

187-
/* Do a clone3() with sizeof(struct clone_args) + 8 in a new PID NS */
188-
if (uid == 0)
189-
test_clone3(CLONE_NEWPID, sizeof(struct __clone_args) + 8, 0,
190-
CLONE3_ARGS_NO_TEST);
191-
else
192-
ksft_test_result_skip("Skipping clone3() with CLONE_NEWPID\n");
304+
for (i = 0; i < ARRAY_SIZE(tests); i++) {
305+
if (tests[i].filter && tests[i].filter()) {
306+
ksft_test_result_skip("%s\n", tests[i].name);
307+
continue;
308+
}
193309

194-
/* Do a clone3() with > page size in a new PID NS */
195-
test_clone3(CLONE_NEWPID, getpagesize() + 8, -E2BIG,
196-
CLONE3_ARGS_NO_TEST);
310+
if (tests[i].size_function)
311+
size = tests[i].size_function();
312+
else
313+
size = tests[i].size;
197314

198-
/* Do a clone3() in a new time namespace */
199-
test_clone3(CLONE_NEWTIME, 0, 0, CLONE3_ARGS_NO_TEST);
315+
ksft_print_msg("Running test '%s'\n", tests[i].name);
200316

201-
/* Do a clone3() with exit signal (SIGCHLD) in flags */
202-
test_clone3(SIGCHLD, 0, -EINVAL, CLONE3_ARGS_NO_TEST);
317+
ksft_test_result(test_clone3(tests[i].flags, size,
318+
tests[i].expected,
319+
tests[i].test_mode),
320+
"%s\n", tests[i].name);
321+
}
203322

204323
ksft_finished();
205324
}

0 commit comments

Comments
 (0)