#include <stdio.h>
#include <assert.h>
#include <getopt.h>
+#include <limits.h>
#include <execinfo.h>
#include <ecoli_log.h>
static int log_level = EC_LOG_INFO;
static int alloc_fail_proba = 0;
+static int seed = 0;
+static size_t alloc_success = 0;
static const char ec_short_options[] =
"h" /* help */
"l:" /* log-level */
"r:" /* random-alloc-fail */
+ "s:" /* seed */
;
#define EC_OPT_HELP "help"
#define EC_OPT_LOG_LEVEL "log-level"
#define EC_OPT_RANDOM_ALLOC_FAIL "random-alloc-fail"
+#define EC_OPT_SEED "seed"
static const struct option ec_long_options[] = {
{EC_OPT_HELP, 1, NULL, 'h'},
{EC_OPT_LOG_LEVEL, 1, NULL, 'l'},
{EC_OPT_RANDOM_ALLOC_FAIL, 1, NULL, 'r'},
+ {EC_OPT_SEED, 1, NULL, 's'},
{NULL, 0, NULL, 0}
};
static void usage(const char *prgname)
{
- printf("%s [options]\n"
+ printf("%s [options] [test1 test2 test3...]\n"
" -h\n"
" --"EC_OPT_HELP"\n"
" Show this help.\n"
" -l <level>\n"
" --"EC_OPT_LOG_LEVEL"=<level>\n"
- " Set log level (0 = no log, 6 = verbose).\n"
+ " Set log level (0 = no log, 7 = verbose).\n"
" -r <probability>\n"
" --"EC_OPT_RANDOM_ALLOC_FAIL"=<probability>\n"
" Cause malloc to fail randomly. This helps to debug\n"
" leaks or crashes in error cases. The probability is\n"
" between 0 and 100.\n"
+ " -s <seed>\n"
+ " --seed=<seed>\n"
+ " Seeds the random number generator. Default is 0.\n"
, prgname);
}
return 0;
}
-static void parse_args(int argc, char **argv)
+static int parse_args(int argc, char **argv)
{
- int opt;
+ int ret, opt;
while ((opt = getopt_long(argc, argv, ec_short_options,
ec_long_options, NULL)) != EOF) {
}
break;
+ case 's': /* seed */
+ if (parse_int(optarg, 0, INT_MAX, &seed, 10) < 0) {
+ printf("Invalid seed value\n");
+ usage(argv[0]);
+ exit(1);
+ }
+ break;
+
default:
usage(argv[0]);
- exit(1);
+ return -1;
}
}
+
+ ret = optind - 1;
+ optind = 1;
+
+ return ret;
}
TAILQ_HEAD(debug_alloc_hdr_list, debug_alloc_hdr);
ec_log(EC_LOG_DEBUG, "%s:%d: info: malloc(%zd) -> %p\n",
file, line, size, ret);
+ if (ret)
+ alloc_success++;
return ret;
}
ec_log(EC_LOG_DEBUG, "%s:%d: info: realloc(%p, %zd) -> %p\n",
file, line, ptr, size, ret);
+ if (ret)
+ alloc_success++;
return ret;
}
int i;
char **buffer;
+ ec_log(EC_LOG_INFO, "%zd successful allocations\n", alloc_success);
+
if (TAILQ_EMPTY(&debug_alloc_hdr_list))
return 0;
int main(int argc, char **argv)
{
- int ret, leaks;
+ int i, ret = 0, leaks;
+
+ ret = parse_args(argc, argv);
+ if (ret < 0)
+ return 1;
- parse_args(argc, argv);
+ argc -= ret;
+ argv += ret;
+
+ srandom(seed);
ec_log_register(debug_log, NULL);
return -1;
}
- ret = ec_test_all();
+ ret = 0;
+ if (argc <= 1) {
+ ret = ec_test_all();
+ } else {
+ for (i = 1; i < argc; i++)
+ ret |= ec_test_one(argv[i]);
+ }
ec_malloc_unregister();
leaks = debug_alloc_dump_leaks();