diff --git a/Makefile b/Makefile index 5486f07d5..669dea1a4 100644 --- a/Makefile +++ b/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 diff --git a/include/haproxy/debug.h b/include/haproxy/debug.h index 9feed8a99..3142185cd 100644 --- a/include/haproxy/debug.h +++ b/include/haproxy/debug.h @@ -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 */ diff --git a/include/haproxy/init-t.h b/include/haproxy/init-t.h index 110171b05..ad17112c0 100644 --- a/include/haproxy/init-t.h +++ b/include/haproxy/init-t.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 */ diff --git a/include/haproxy/init.h b/include/haproxy/init.h index 6e3047567..ca059e376 100644 --- a/include/haproxy/init.h +++ b/include/haproxy/init.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)) diff --git a/src/debug.c b/src/debug.c index 147e73ea1..d7ac90f47 100644 --- a/src/debug.c +++ b/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) diff --git a/src/haproxy.c b/src/haproxy.c index 31d20d55f..90b89f9b8 100644 --- a/src/haproxy.c +++ b/src/haproxy.c @@ -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) {