Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 25 additions & 10 deletions src/arguments.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ enum TdoError tdo_arguments_parse(struct TdoArguments *args, int argc, char **ar
}
} else {
// flag
if (strncmp(s, "-t", 3) == 0) {
if (strcmp(s, "-t") == 0) {
if (argc <= 1) {
fprintf(stderr, "Missing test argument to '-t'\n");
result = TDO_ERROR_ARG_PARSE;
Expand All @@ -43,9 +43,24 @@ enum TdoError tdo_arguments_parse(struct TdoArguments *args, int argc, char **ar
args->single_test = argv[0];
}
} else if (strncmp(s, "-j", 2) == 0) {
char const *job_str = NULL;
if (strcmp(s, "-j") == 0) {
if (argc <= 1) {
fprintf(stderr, "Missing job argument to '-j'\n");
result = TDO_ERROR_ARG_PARSE;
argc -= 1; argv += 1;
continue;
} else {
argc -= 1; argv += 1;
job_str = argv[0];
}
} else {
job_str = s + 2;
}

errno = 0;
char *err;
unsigned long threads = strtoul(s + 2, &err, 10);
unsigned long threads = strtoul(job_str, &err, 10);
if (errno) {
perror("Could not parse amount of processes");
result = TDO_ERROR_ARG_PARSE;
Expand All @@ -61,27 +76,27 @@ enum TdoError tdo_arguments_parse(struct TdoArguments *args, int argc, char **ar
} else {
args->processes = (size_t) threads;
}
} else if (strncmp(s, "-o", 3) == 0) {
} else if (strcmp(s, "-o") == 0) {
if (argc <= 1) {
fprintf(stderr, "Missing output file argument to '-o'\n");
result = TDO_ERROR_ARG_PARSE;
} else {
argc -= 1; argv += 1;
args->output = argv[0];
}
} else if (strncmp(s, "-f", 3) == 0) {
} else if (strcmp(s, "-f") == 0) {
args->overwrite = true;
} else if (strncmp(s, "--internal-status", 18) == 0) {
} else if (strcmp(s, "--internal-status") == 0) {
if (argc <= 1) {
fprintf(stderr, "Missing status file\n");
result = TDO_ERROR_ARG_PARSE;
} else {
argc -= 1; argv += 1;
args->internal_status = argv[0];
}
} else if (strncmp(s, "--timeout", 10) == 0) {
} else if (strcmp(s, "--timeout") == 0) {
if (argc <= 1) {
fprintf(stderr, "Missing timeout argument\n");
fprintf(stderr, "Missing timeout argument to '--timeout'\n");
result = TDO_ERROR_ARG_PARSE;
} else {
argc -= 1; argv += 1;
Expand All @@ -91,13 +106,13 @@ enum TdoError tdo_arguments_parse(struct TdoArguments *args, int argc, char **ar
char *err;
float timeout = strtof(timeout_str, &err);
if (errno) {
perror("Could not parse amount of processes");
perror("Could not parse timeout");
result = TDO_ERROR_ARG_PARSE;
} else if (*err != '\0') {
fprintf(stderr, "Could not parse amount of threads: '%s'\n", timeout_str);
fprintf(stderr, "Could not parse timeout: '%s'\n", timeout_str);
result = TDO_ERROR_ARG_PARSE;
} else if (timeout <= 0) {
fprintf(stderr, "Amount of processes must be strictly positive, got %f\n", timeout);
fprintf(stderr, "Timeout must be strictly positive, got %f\n", timeout);
result = TDO_ERROR_ARG_PARSE;
} else {
args->time_limit = timeout;
Expand Down
42 changes: 42 additions & 0 deletions src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,52 @@

#include <errno.h>
#include <stdio.h>
#include <string.h>

static const char *tdo_help_text =
"Usage: tdo [OPTIONS] [TEST_FILE]\n"
" tdo [OPTIONS] -t \"TEST_DEFINITION\"\n"
" cat tests.txt | tdo [OPTIONS]\n"
"\n"
"A C99 test runner that executes tests defined by shared library symbols.\n"
"Every test is executed in a separate process which ensures that they do not\n"
"interact.\n"
"\n"
"Arguments:\n"
" TEST_FILE Path to a file containing test definitions. If omitted \n"
" and no -t flag is provided, definitions are read \n"
" from standard input (stdin).\n"
"\n"
"Options:\n"
" -t \"TEST_DEFINITION\" Run a single test definition string directly.\n"
" -j [N] Run tests in parallel using N processes (default: 1).\n"
" -o FILE Write results to the specified FILE.\n"
" -f Force overwrite the output file if it already exists.\n"
" --timeout SECONDS Set a maximum execution time per test (default: 5.0).\n"
" -h, --help Display this help message and exit.\n"
"\n"
"Test Definition Format:\n"
" Definitions follow a \"test-first\" structure:\n"
" test::PATH::SYMBOL [before::PATH::SYMBOL] [after::PATH::SYMBOL] ...\n"
"\n"
" - PATH: The path to the shared library (e.g., .so, .dll, or .dylib).\n"
" - SYMBOL: The name of the exported function to execute.\n"
"\n"
" Definitions can include any number of 'before' and 'after' hooks.\n"
" Example:\n"
" test::./lib.so::test_math before::./lib.so::setup after::./lib.so::clean\n"
;

int main(int argc, char **argv) {
enum TdoError result = TDO_ERROR_UNKNOWN;

for (int i = 0; i < argc; i++) {
if (strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "--help") == 0) {
fprintf(stderr, "%s", tdo_help_text);
return TDO_ERROR_OK;
}
}

struct TdoArguments args;
result = tdo_arguments_parse(&args, argc, argv);
if (result != TDO_ERROR_OK) goto error_parse_args;
Expand Down
Loading