aboutsummaryrefslogtreecommitdiff
path: root/include/tst_test.h
blob: 75c2109b9945d3ad6f9dcd61267b7119d5f0db8c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * Copyright (c) 2015-2016 Cyril Hrubis <chrubis@suse.cz>
 * Copyright (c) Linux Test Project, 2016-2019
 */

#ifndef TST_TEST_H__
#define TST_TEST_H__

#ifdef __TEST_H__
# error Oldlib test.h already included
#endif /* __TEST_H__ */

#include <unistd.h>
#include <limits.h>
#include <string.h>
#include <errno.h>

#include "tst_common.h"
#include "tst_res_flags.h"
#include "tst_test_macros.h"
#include "tst_checkpoint.h"
#include "tst_device.h"
#include "tst_mkfs.h"
#include "tst_fs.h"
#include "tst_pid.h"
#include "tst_cmd.h"
#include "tst_cpu.h"
#include "tst_process_state.h"
#include "tst_atomic.h"
#include "tst_kvercmp.h"
#include "tst_kernel.h"
#include "tst_minmax.h"
#include "tst_get_bad_addr.h"
#include "tst_path_has_mnt_flags.h"
#include "tst_sys_conf.h"
#include "tst_coredump.h"
#include "tst_buffers.h"
#include "tst_capability.h"
#include "tst_hugepage.h"
#include "tst_assert.h"
#include "tst_lockdown.h"
#include "tst_fips.h"
#include "tst_taint.h"
#include "tst_memutils.h"
#include "tst_arch.h"

/*
 * Reports testcase result.
 */
void tst_res_(const char *file, const int lineno, int ttype,
              const char *fmt, ...)
              __attribute__ ((format (printf, 4, 5)));

#define tst_res(ttype, arg_fmt, ...) \
	({									\
		TST_RES_SUPPORTS_TCONF_TFAIL_TINFO_TPASS_TWARN(!((TTYPE_RESULT(ttype) ?: TCONF) & \
			(TCONF | TFAIL | TINFO | TPASS | TWARN))); 				\
		tst_res_(__FILE__, __LINE__, (ttype), (arg_fmt), ##__VA_ARGS__);\
	})

void tst_resm_hexd_(const char *file, const int lineno, int ttype,
	const void *buf, size_t size, const char *arg_fmt, ...)
	__attribute__ ((format (printf, 6, 7)));

#define tst_res_hexd(ttype, buf, size, arg_fmt, ...) \
	tst_resm_hexd_(__FILE__, __LINE__, (ttype), (buf), (size), \
			(arg_fmt), ##__VA_ARGS__)

/*
 * Reports result and exits a test.
 */
void tst_brk_(const char *file, const int lineno, int ttype,
              const char *fmt, ...)
              __attribute__ ((format (printf, 4, 5)));

#define tst_brk(ttype, arg_fmt, ...)						\
	({									\
		TST_BRK_SUPPORTS_ONLY_TCONF_TBROK(!((ttype) &			\
			(TBROK | TCONF | TFAIL))); 				\
		tst_brk_(__FILE__, __LINE__, (ttype), (arg_fmt), ##__VA_ARGS__);\
	})

void tst_printf(const char *const fmt, ...)
		__attribute__((nonnull(1), format (printf, 1, 2)));

/* flush stderr and stdout */
void tst_flush(void);

pid_t safe_fork(const char *filename, unsigned int lineno);
#define SAFE_FORK() \
	safe_fork(__FILE__, __LINE__)

#define TST_TRACE(expr)	                                            \
	({int ret = expr;                                           \
	  ret != 0 ? tst_res(TINFO, #expr " failed"), ret : ret; }) \

/*
 * Functions to convert ERRNO to its name and SIGNAL to its name.
 */
const char *tst_strerrno(int err);
const char *tst_strsig(int sig);
/*
 * Returns string describing status as returned by wait().
 *
 * BEWARE: Not thread safe.
 */
const char *tst_strstatus(int status);

#include "tst_safe_macros.h"
#include "tst_safe_file_ops.h"
#include "tst_safe_net.h"
#include "tst_clone.h"
#include "tst_cgroup.h"

/*
 * Wait for all children and exit with TBROK if
 * any of them returned a non-zero exit status.
 */
void tst_reap_children(void);

struct tst_option {
	char *optstr;
	char **arg;
	char *help;
};

/*
 * Options parsing helpers.
 *
 * If str is NULL these are No-op.
 *
 * On failure non-zero (errno) is returned.
 */
int tst_parse_int(const char *str, int *val, int min, int max);
int tst_parse_long(const char *str, long *val, long min, long max);
int tst_parse_float(const char *str, float *val, float min, float max);
int tst_parse_filesize(const char *str, long long *val, long long min, long long max);

struct tst_tag {
	const char *name;
	const char *value;
};

extern unsigned int tst_variant;

#define TST_NO_HUGEPAGES ((unsigned long)-1)

#define TST_UNLIMITED_RUNTIME (-1)

struct tst_test {
	/* number of tests available in test() function */
	unsigned int tcnt;

	struct tst_option *options;

	const char *min_kver;

	/*
	 * The supported_archs is a NULL terminated list of archs the test
	 * does support.
	 */
	const char *const *supported_archs;

	/* If set the test is compiled out */
	const char *tconf_msg;

	int needs_tmpdir:1;
	int needs_root:1;
	int forks_child:1;
	int needs_device:1;
	int needs_checkpoints:1;
	int needs_overlay:1;
	int format_device:1;
	int mount_device:1;
	int needs_rofs:1;
	int child_needs_reinit:1;
	int needs_devfs:1;
	int restore_wallclock:1;

	/*
	 * If set the test function will be executed for all available
	 * filesystems and the current filesystem type would be set in the
	 * tst_device->fs_type.
	 *
	 * The test setup and cleanup are executed before/after __EACH__ call
	 * to the test function.
	 */
	int all_filesystems:1;

	int skip_in_lockdown:1;
	int skip_in_secureboot:1;
	int skip_in_compat:1;

	/*
	 * If set, the hugetlbfs will be mounted at .mntpoint.
	 */
	int needs_hugetlbfs:1;

	/*
	 * The skip_filesystems is a NULL terminated list of filesystems the
	 * test does not support. It can also be used to disable whole class of
	 * filesystems with a special keywords such as "fuse".
	 */
	const char *const *skip_filesystems;

	/* Minimum number of online CPU required by the test */
	unsigned long min_cpus;

	/* Minimum size(MB) of MemAvailable required by the test */
	unsigned long min_mem_avail;

	/* Minimum size(MB) of SwapFree required by the test */
	unsigned long min_swap_avail;

	/*
	 * Two policies for reserving hugepage:
	 *
	 * TST_REQUEST:
	 *   It will try the best to reserve available huge pages and return the number
	 *   of available hugepages in tst_hugepages, which may be 0 if hugepages are
	 *   not supported at all.
	 *
	 * TST_NEEDS:
	 *   This is an enforced requirement, LTP should strictly do hpages applying and
	 *   guarantee the 'HugePages_Free' no less than pages which makes that test can
	 *   use these specified numbers correctly. Otherwise, test exits with TCONF if
	 *   the attempt to reserve hugepages fails or reserves less than requested.
	 *
	 * With success test stores the reserved hugepage number in 'tst_hugepages. For
	 * the system without hugetlb supporting, variable 'tst_hugepages' will be set to 0.
	 * If the hugepage number needs to be set to 0 on supported hugetlb system, please
	 * use '.hugepages = {TST_NO_HUGEPAGES}'.
	 *
	 * Also, we do cleanup and restore work for the hpages resetting automatically.
	 */
	struct tst_hugepage hugepages;

	/*
	 * If set to non-zero, call tst_taint_init(taint_check) during setup
	 * and check kernel taint at the end of the test. If all_filesystems
	 * is non-zero, taint check will be performed after each FS test and
	 * testing will be terminated by TBROK if taint is detected.
	 */
	unsigned int taint_check;

	/*
	 * If set non-zero denotes number of test variant, the test is executed
	 * variants times each time with tst_variant set to different number.
	 *
	 * This allows us to run the same test for different settings. The
	 * intended use is to test different syscall wrappers/variants but the
	 * API is generic and does not limit the usage in any way.
	 */
	unsigned int test_variants;

	/* Minimal device size in megabytes */
	unsigned int dev_min_size;

	/* Device filesystem type override NULL == default */
	const char *dev_fs_type;

	/* Options passed to SAFE_MKFS() when format_device is set */
	const char *const *dev_fs_opts;
	const char *const *dev_extra_opts;

	/* Device mount options, used if mount_device is set */
	const char *mntpoint;
	unsigned int mnt_flags;
	void *mnt_data;

	/*
	 * Maximal test runtime in seconds.
	 *
	 * Any test that runs for more than a second or two should set this and
	 * also use tst_remaining_runtime() to exit when runtime was used up.
	 * Tests may finish sooner, for example if requested number of
	 * iterations was reached before the runtime runs out.
	 *
	 * If test runtime cannot be know in advance it should be set to
	 * TST_UNLIMITED_RUNTIME.
	 */
	int max_runtime;

	void (*setup)(void);
	void (*cleanup)(void);

	void (*test)(unsigned int test_nr);
	void (*test_all)(void);

	/* Syscall name used by the timer measurement library */
	const char *scall;

	/* Sampling function for timer measurement testcases */
	int (*sample)(int clk_id, long long usec);

	/* NULL terminated array of resource file names */
	const char *const *resource_files;

	/* NULL terminated array of needed kernel drivers */
	const char * const *needs_drivers;

	/*
	 * {NULL, NULL} terminated array of (/proc, /sys) files to save
	 * before setup and restore after cleanup
	 */
	const struct tst_path_val *save_restore;

	/*
	 * NULL terminated array of kernel config options required for the
	 * test.
	 */
	const char *const *needs_kconfigs;

	/*
	 * {NULL, NULL} terminated array to be allocated buffers.
	 */
	struct tst_buffers *bufs;

	/*
	 * {NULL, NULL} terminated array of capability settings
	 */
	struct tst_cap *caps;

	/*
	 * {NULL, NULL} terminated array of tags.
	 */
	const struct tst_tag *tags;

	/* NULL terminated array of required commands */
	const char *const *needs_cmds;

	/* Requires a particular CGroup API version. */
	const enum tst_cg_ver needs_cgroup_ver;

	/* {} terminated array of required CGroup controllers */
	const char *const *needs_cgroup_ctrls;
};

/*
 * Runs tests.
 */
void tst_run_tcases(int argc, char *argv[], struct tst_test *self)
                    __attribute__ ((noreturn));

#define IPC_ENV_VAR "LTP_IPC_PATH"

/*
 * Does library initialization for child processes started by exec()
 *
 * The LTP_IPC_PATH variable must be passed to the program environment.
 */
void tst_reinit(void);

unsigned int tst_multiply_timeout(unsigned int timeout);

/*
 * Returns remaining test runtime. Test that runs for more than a few seconds
 * should check if they should exit by calling this function regularly.
 *
 * The function returns remaining runtime in seconds. If runtime was used up
 * zero is returned.
 */
unsigned int tst_remaining_runtime(void);

/*
 * Sets maximal test runtime in seconds.
 */
void tst_set_max_runtime(int max_runtime);

/*
 * Create and open a random file inside the given dir path.
 * It unlinks the file after opening and return file descriptor.
 */
int tst_creat_unlinked(const char *path, int flags);

/*
 * Returns path to the test temporary directory in a newly allocated buffer.
 */
char *tst_get_tmpdir(void);

/*
 * Returns path to the test temporary directory root (TMPDIR).
 */
const char *tst_get_tmpdir_root(void);

/*
 * Validates exit status of child processes
 */
int tst_validate_children_(const char *file, const int lineno,
	unsigned int count);
#define tst_validate_children(child_count) \
	tst_validate_children_(__FILE__, __LINE__, (child_count))

#ifndef TST_NO_DEFAULT_MAIN

static struct tst_test test;

int main(int argc, char *argv[])
{
	tst_run_tcases(argc, argv, &test);
}

#endif /* TST_NO_DEFAULT_MAIN */

#define TST_TEST_TCONF(message)                                 \
        static struct tst_test test = { .tconf_msg = message  } \

#endif	/* TST_TEST_H__ */