DEBUG: init: add a way to register functions for unit tests
Doing unit tests with haproxy was always a bit difficult, some of the function you want to test would depend on the buffer or trash buffer initialisation of HAProxy, so building a separate main() for them is quite hard. This patch adds a way to register a function that can be called with the "-U" parameter on the command line, will be executed just after step_init_1() and will exit the process with its return value as an exit code. When using the -U option, every keywords after this option is passed to the callback and could be used as a parameter, letting the capability to handle complex arguments if required by the test. HAProxy need to be built with DEBUG_UNIT to activate this feature.
This commit is contained in:
parent
4dc0ba233e
commit
a647839954
2
Makefile
2
Makefile
@ -262,7 +262,7 @@ endif
|
||||
# DEBUG_NO_POOLS, DEBUG_FAIL_ALLOC, DEBUG_STRICT_ACTION=[0-3], DEBUG_HPACK,
|
||||
# DEBUG_AUTH, DEBUG_SPOE, DEBUG_UAF, DEBUG_THREAD, DEBUG_STRICT, DEBUG_DEV,
|
||||
# DEBUG_TASK, DEBUG_MEMORY_POOLS, DEBUG_POOL_TRACING, DEBUG_QPACK, DEBUG_LIST,
|
||||
# DEBUG_GLITCHES, DEBUG_STRESS.
|
||||
# DEBUG_GLITCHES, DEBUG_STRESS, DEBUG_UNIT.
|
||||
DEBUG =
|
||||
|
||||
#### Trace options
|
||||
|
@ -38,4 +38,8 @@ void post_mortem_add_component(const char *name, const char *version,
|
||||
const char *toolchain, const char *toolchain_opts,
|
||||
const char *build_settings, const char *path);
|
||||
|
||||
#ifdef DEBUG_UNIT
|
||||
void list_unittests();
|
||||
#endif
|
||||
|
||||
#endif /* _HAPROXY_DEBUG_H */
|
||||
|
@ -61,4 +61,10 @@ struct per_thread_deinit_fct {
|
||||
void (*fct)();
|
||||
};
|
||||
|
||||
struct unittest_fct {
|
||||
struct list list;
|
||||
const char *name;
|
||||
int (*fct)(int argc, char **argv);
|
||||
};
|
||||
|
||||
#endif /* _HAPROXY_INIT_T_H */
|
||||
|
@ -32,6 +32,13 @@ void hap_register_per_thread_init(int (*fct)());
|
||||
void hap_register_per_thread_deinit(void (*fct)());
|
||||
void hap_register_per_thread_free(void (*fct)());
|
||||
|
||||
|
||||
#ifdef DEBUG_UNIT
|
||||
void hap_register_unittest(const char *name, int (*fct)());
|
||||
#else
|
||||
#define hap_register_unittest(a,b) ({})
|
||||
#endif
|
||||
|
||||
/* simplified way to declare a pre-check callback in a file */
|
||||
#define REGISTER_PRE_CHECK(fct) \
|
||||
INITCALL1(STG_REGISTER, hap_register_pre_check, (fct))
|
||||
|
25
src/debug.c
25
src/debug.c
@ -2764,6 +2764,31 @@ static int feed_post_mortem_late()
|
||||
REGISTER_PER_THREAD_INIT(feed_post_mortem_late);
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG_UNIT
|
||||
|
||||
extern struct list unittest_list;
|
||||
|
||||
void list_unittests()
|
||||
{
|
||||
struct unittest_fct *unit;
|
||||
int found = 0;
|
||||
|
||||
fprintf(stdout, "Unit tests list :");
|
||||
|
||||
list_for_each_entry(unit, &unittest_list, list) {
|
||||
fprintf(stdout, " %s", unit->name);
|
||||
found = 1;
|
||||
}
|
||||
|
||||
if (!found)
|
||||
fprintf(stdout, " none");
|
||||
|
||||
fprintf(stdout, "\n");
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/* register cli keywords */
|
||||
static struct cli_kw_list cli_kws = {{ },{
|
||||
#if !defined(USE_OBSOLETE_LINKER)
|
||||
|
@ -250,6 +250,11 @@ char **old_argv = NULL; /* previous argv but cleaned up */
|
||||
|
||||
struct list proc_list = LIST_HEAD_INIT(proc_list);
|
||||
|
||||
#ifdef DEBUG_UNIT
|
||||
struct list unittest_list = LIST_HEAD_INIT(unittest_list);
|
||||
static int unittest_argc = -1;
|
||||
#endif
|
||||
|
||||
int master = 0; /* 1 if in master, 0 if in child */
|
||||
|
||||
/* per-boot randomness */
|
||||
@ -396,6 +401,22 @@ void hap_register_feature(const char *name)
|
||||
must_free = 1;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_UNIT
|
||||
/* register a function that could be registered in "-U" argument */
|
||||
void hap_register_unittest(const char *name, int (*fct)(int argc, char **argv))
|
||||
{
|
||||
struct unittest_fct *unit;
|
||||
|
||||
if (!name || !fct)
|
||||
return;
|
||||
|
||||
unit = calloc(1, sizeof(*unit));
|
||||
unit->fct = fct;
|
||||
unit->name = name;
|
||||
LIST_APPEND(&unittest_list, &unit->list);
|
||||
}
|
||||
#endif
|
||||
|
||||
#define VERSION_MAX_ELTS 7
|
||||
|
||||
/* This function splits an haproxy version string into an array of integers.
|
||||
@ -602,6 +623,10 @@ static void display_build_opts()
|
||||
|
||||
putchar('\n');
|
||||
|
||||
#ifdef DEBUG_UNIT
|
||||
list_unittests();
|
||||
putchar('\n');
|
||||
#endif
|
||||
list_pollers(stdout);
|
||||
putchar('\n');
|
||||
list_mux_proto(stdout);
|
||||
@ -1629,6 +1654,19 @@ static void init_args(int argc, char **argv)
|
||||
nb_oldpids++;
|
||||
}
|
||||
}
|
||||
#ifdef DEBUG_UNIT
|
||||
else if (*flag == 'U') {
|
||||
if (argc <= 1) {
|
||||
ha_alert("-U takes a least a unittest name in argument, and must be the last option\n");
|
||||
usage(progname);
|
||||
}
|
||||
/* this is the last option, we keep the option position */
|
||||
argv++;
|
||||
argc--;
|
||||
unittest_argc = argc;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
else if (flag[0] == '-' && flag[1] == 0) { /* "--" */
|
||||
/* now that's a cfgfile list */
|
||||
argv++; argc--;
|
||||
@ -1912,7 +1950,6 @@ static void bind_listeners()
|
||||
select(0, NULL, NULL, NULL, &w);
|
||||
retry--;
|
||||
}
|
||||
|
||||
/* Note: protocol_bind_all() sends an alert when it fails. */
|
||||
if ((err & ~ERR_WARN) != ERR_NONE) {
|
||||
ha_alert("[%s.main()] Some protocols failed to start their listeners! Exiting.\n", progname);
|
||||
@ -3133,6 +3170,26 @@ int main(int argc, char **argv)
|
||||
*/
|
||||
step_init_1();
|
||||
|
||||
/* call a function to be called with -U in order to make some tests */
|
||||
#ifdef DEBUG_UNIT
|
||||
if (unittest_argc > -1) {
|
||||
struct unittest_fct *unit;
|
||||
int ret = 1;
|
||||
int argc_start = argc - unittest_argc;
|
||||
|
||||
list_for_each_entry(unit, &unittest_list, list) {
|
||||
|
||||
if (strcmp(unit->name, argv[argc_start]) == 0) {
|
||||
ret = unit->fct(unittest_argc, argv + argc_start);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
exit(ret);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* deserialize processes list, if we do reload in master-worker mode */
|
||||
if ((getenv("HAPROXY_MWORKER_REEXEC") != NULL)) {
|
||||
if (mworker_env_to_proc_list() < 0) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user