summaryrefslogtreecommitdiff
path: root/lib/get-test-job.c
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@gmail.com>2022-07-07 23:11:25 -0400
committerKent Overstreet <kent.overstreet@gmail.com>2022-07-07 23:52:08 -0400
commit011cb21e8248e08d3c2775e9864096c29caec507 (patch)
tree96d77c84a41b810ed2990e00c8a3f38aeae8223c /lib/get-test-job.c
parent6ec253d2b80a123861cad166115faba4b862c35d (diff)
get-test-job: Query for subtests, and write per-subtest lockfiles
Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com
Diffstat (limited to 'lib/get-test-job.c')
-rw-r--r--lib/get-test-job.c236
1 files changed, 175 insertions, 61 deletions
diff --git a/lib/get-test-job.c b/lib/get-test-job.c
index 193544b..665249f 100644
--- a/lib/get-test-job.c
+++ b/lib/get-test-job.c
@@ -13,8 +13,12 @@
#include <sys/types.h>
#include <unistd.h>
+#define HAVE_STATEMENT_EXPR 1
+#include "darray/darray.h"
+
static char *outdir = NULL;
static char *branches_to_test = NULL;
+static bool verbose = false;
#define die(msg, ...) \
do { \
@@ -47,7 +51,7 @@ static void strim(char *line)
*p = 0;
}
-static char *test_basename(char *str)
+static char *test_basename(const char *str)
{
char *p = strrchr(str, '/');
char *ret = strdup(p ? p + 1 : str);
@@ -58,105 +62,216 @@ static char *test_basename(char *str)
return ret;
}
-static void branch_get_next_commit_and_test(char *branch,
- char **ret_commit,
- char *test,
- unsigned *age)
+typedef darray(char *) strings;
+
+static void strings_free(strings *strs)
+{
+ char **s;
+
+ darray_foreach(s, *strs)
+ free(*s);
+ darray_free(*strs);
+
+ memset(strs, 0, sizeof(*strs));
+}
+
+typedef struct {
+ char *branch;
+ char *commit;
+ unsigned age;
+ char *test;
+ strings subtests;
+} test_job;
+
+static void test_job_free(test_job *job)
+{
+ free(job->branch);
+ free(job->commit);
+ free(job->test);
+ strings_free(&job->subtests);
+ memset(job, 0, sizeof(*job));
+}
+
+static strings get_subtests(char *test_path)
+{
+ darray_char output;
+ strings ret;
+ size_t bytes_read;
+
+ darray_init(output);
+ darray_init(ret);
+
+ char *cmd = mprintf("%s list-tests", test_path);
+ FILE *f = popen(cmd, "r");
+ free(cmd);
+
+ if (!f)
+ die("error executing %s", test_path);
+
+ do {
+ darray_make_room(output, 4096);
+
+ bytes_read = fread(output.item + output.size,
+ 1, 4096, f);
+ output.size += bytes_read;
+ } while (bytes_read);
+
+ pclose(f);
+
+ char *subtest, *p = output.item;
+ while ((subtest = strtok(p, " \t\n"))) {
+ darray_push(ret, strdup(subtest));
+ p = NULL;
+ }
+
+ darray_free(output);
+
+ if (darray_empty(ret))
+ die("error getting subtests from %s", test_path);
+
+ return ret;
+}
+
+static bool lockfile_exists(const char *commit,
+ const char *test_path,
+ const char *subtest,
+ bool create)
+{
+ char *test_name = test_basename(test_path);
+ char *commitdir = mprintf("%s/%s", outdir, commit);
+ char *testdir = mprintf("%s/%s.%s", commitdir, test_name, subtest);
+ char *lockfile = mprintf("%s/status",
+ testdir, subtest);
+ bool exists;
+
+ if (!create) {
+ exists = access(lockfile, F_OK) == 0;
+ } else {
+ mkdir(commitdir, 0755);
+ mkdir(testdir, 0755);
+ int fd = open(lockfile, O_RDWR|O_CREAT|O_EXCL, 0644);
+ exists = fd < 0;
+ if (!exists)
+ close(fd);
+ }
+
+ free(lockfile);
+ free(testdir);
+ free(commitdir);
+ free(test_name);
+
+ return exists;
+}
+
+static test_job branch_get_next_test_job(char *branch,
+ char *test_path,
+ strings subtests)
{
char *cmd = mprintf("git log --pretty=format:%H %s", branch);
FILE *commits = popen(cmd, "r");
char *commit = NULL;
size_t n = 0;
ssize_t len;
+ test_job ret;
- *age = 0;
+ memset(&ret, 0, sizeof(ret));
while ((len = getline(&commit, &n, commits)) >= 0) {
strim(commit);
- char *lockfile = mprintf("%s/%s/%s", outdir, commit, test);
- bool exists = access(lockfile, F_OK) == 0;
- free(lockfile);
-
- if (!exists) {
- *ret_commit = strdup(commit);
+ char **subtest;
+ darray_foreach(subtest, subtests)
+ if (!lockfile_exists(commit, test_path, *subtest, false)) {
+ darray_push(ret.subtests, strdup(*subtest));
+ if (darray_size(ret.subtests) > 20)
+ break;
+ }
+
+ if (!darray_empty(ret.subtests)) {
+ ret.branch = strdup(branch);
+ ret.commit = strdup(commit);
+ ret.test = strdup(test_path);
goto success;
}
- (*age)++;
+ ret.age++;
}
fprintf(stderr, "error looking up commits on branch %s\n", branch);
success:
fclose(commits);
free(commit);
free(cmd);
+ return ret;
}
-static void get_best_branch_commit_test(char **ret_branch,
- char **ret_commit,
- char **ret_test)
+static test_job get_best_test_job()
{
FILE *branches = fopen(branches_to_test, "r");
char *line = NULL;
size_t n = 0;
ssize_t len;
- unsigned best_age = 0;
+ test_job best;
+
+ memset(&best, 0, sizeof(best));
if (!branches)
die("error opening %s: %m", branches_to_test);
- *ret_branch = NULL;
- *ret_commit = NULL;
- *ret_test = NULL;
-
while ((len = getline(&line, &n, branches)) >= 0) {
- char *commit = NULL;
char *branch = strtok(line, " \t\n");
- char *test = strtok(NULL, " \t\n");
- char *testname;
- unsigned age;
+ char *test_path = strtok(NULL, " \t\n");
- if (!branch || !test)
+ if (!branch || !test_path)
continue;
- testname = test_basename(test);
- //fprintf(stderr, "branch %s test %s\n", branch, test);
+ strings subtests = get_subtests(test_path);
- branch_get_next_commit_and_test(branch, &commit, testname, &age);
- free(testname);
+ if (verbose)
+ fprintf(stderr, "branch %s test %s\n", branch, test_path);
- if (!*ret_branch || age < best_age) {
- free(*ret_branch);
- free(*ret_commit);
- free(*ret_test);
+ test_job job = branch_get_next_test_job(branch, test_path, subtests);
- *ret_branch = strdup(branch);
- *ret_test = strdup(test);
- *ret_commit = commit;
- best_age = age;
+ strings_free(&subtests);
+
+ if (!best.branch || job.age < best.age) {
+ test_job_free(&best);
+ best = job;
+ } else {
+ test_job_free(&job);
}
}
- if (!*ret_branch)
+ if (!best.branch)
die("Nothing found");
fclose(branches);
free(line);
+ return best;
}
void usage(void)
{
- puts("get-test-job: get a test job and create lockfile");
+ puts("get-test-job: get a test job and create lockfile\n"
+ "Usage: get-test-job [OPTIONS]\n"
+ "\n"
+ "Options\n"
+ " -b file List of branches to test and tests to run\n"
+ " -o dir Directory for tests results\n"
+ " -v Verbose\n"
+ " -h Display this help and exit");
exit(EXIT_SUCCESS);
}
int main(int argc, char *argv[])
{
- char *branch, *commit, *test, *testname;
- bool created;
int opt;
+ test_job job;
+ strings subtests;
+ char **subtest;
+
+ memset(&job, 0, sizeof(job));
- while ((opt = getopt(argc, argv, "b:o:")) != -1) {
+ while ((opt = getopt(argc, argv, "b:o:vh")) != -1) {
switch (opt) {
case 'b':
branches_to_test = strdup(optarg);
@@ -164,6 +279,9 @@ int main(int argc, char *argv[])
case 'o':
outdir = strdup(optarg);
break;
+ case 'v':
+ verbose = true;
+ break;
case 'h':
usage();
exit(EXIT_SUCCESS);
@@ -177,26 +295,22 @@ int main(int argc, char *argv[])
die("required argument missing");
do {
- get_best_branch_commit_test(&branch, &commit, &test);
+ test_job_free(&job);
+ job = get_best_test_job();
- //fprintf(stderr, "got %s %s %s\n", branch, commit, test);
+ if (verbose)
+ fprintf(stderr, "got %s %s %s age %u\n",
+ job.branch, job.commit, job.test, job.age);
- char *commitdir = mprintf("%s/%s", outdir, commit);
- mkdir(commitdir, 0755);
-
- testname = test_basename(test);
-
- char *lockfile = mprintf("%s/%s", commitdir, testname);
-
- //fprintf(stderr, "lockfile %s\n", lockfile);
-
- int fd = open(lockfile, O_RDWR|O_CREAT|O_EXCL, 0644);
- fprintf(stderr, "fd %i\n", fd);
- created = fd >= 0;
+ darray_init(subtests);
- free(commitdir);
- free(lockfile);
- } while (!created);
+ darray_foreach(subtest, job.subtests)
+ if (!lockfile_exists(job.commit, job.test, *subtest, true))
+ darray_push(subtests, *subtest);
+ } while (darray_empty(subtests));
- printf("%s %s %s\n", branch, commit, test);
+ printf("%s %s %s", job.branch, job.commit, job.test);
+ darray_foreach(subtest, subtests)
+ printf(" %s", *subtest);
+ printf("\n");
}