summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@gmail.com>2022-07-01 22:22:46 -0400
committerKent Overstreet <kent.overstreet@gmail.com>2022-07-01 22:25:03 -0400
commit6f332d6a57589cff5b8e4505fa5d05813cc425a7 (patch)
tree1628b52689a054fa083450e686aa8ac5b5cc72a2
parent713880f92d32b2e24f4f6abc2206cdef9c45ff9d (diff)
get-test-job
New tool for getting a test job and creating a lockfile. Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com>
-rw-r--r--.gitignore1
-rw-r--r--lib/Makefile1
-rw-r--r--lib/get-test-job.c202
3 files changed, 204 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
index 4b6d3fc..7e60d1d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,3 +5,4 @@ tags
*.tags
lwip-connect
qemu-wrapper
+get-test-job
diff --git a/lib/Makefile b/lib/Makefile
index 445c207..b9c5a4b 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -1,4 +1,5 @@
CFLAGS=-Wall -g -O2
qemu-wrapper:
+get-test-job:
lwip-connect: LDLIBS=-llwipv6
diff --git a/lib/get-test-job.c b/lib/get-test-job.c
new file mode 100644
index 0000000..193544b
--- /dev/null
+++ b/lib/get-test-job.c
@@ -0,0 +1,202 @@
+#define _GNU_SOURCE
+
+#include <ctype.h>
+#include <getopt.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdarg.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+static char *outdir = NULL;
+static char *branches_to_test = NULL;
+
+#define die(msg, ...) \
+do { \
+ fprintf(stderr, msg "\n", ##__VA_ARGS__); \
+ exit(EXIT_FAILURE); \
+} while (0)
+
+static char *mprintf(const char *fmt, ...)
+{
+ va_list args;
+ char *str;
+ int ret;
+
+ va_start(args, fmt);
+ ret = vasprintf(&str, fmt, args);
+ va_end(args);
+
+ if (ret < 0)
+ die("insufficient memory");
+
+ return str;
+}
+
+static void strim(char *line)
+{
+ char *p = line;
+
+ while (isalnum(*p))
+ p++;
+ *p = 0;
+}
+
+static char *test_basename(char *str)
+{
+ char *p = strrchr(str, '/');
+ char *ret = strdup(p ? p + 1 : str);
+
+ p = strstr(ret, ".ktest");
+ if (p)
+ *p = 0;
+ return ret;
+}
+
+static void branch_get_next_commit_and_test(char *branch,
+ char **ret_commit,
+ char *test,
+ unsigned *age)
+{
+ 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;
+
+ *age = 0;
+
+ 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);
+ goto success;
+ }
+
+ (*age)++;
+ }
+ fprintf(stderr, "error looking up commits on branch %s\n", branch);
+success:
+ fclose(commits);
+ free(commit);
+ free(cmd);
+}
+
+static void get_best_branch_commit_test(char **ret_branch,
+ char **ret_commit,
+ char **ret_test)
+{
+ FILE *branches = fopen(branches_to_test, "r");
+ char *line = NULL;
+ size_t n = 0;
+ ssize_t len;
+ unsigned best_age = 0;
+
+ 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;
+
+ if (!branch || !test)
+ continue;
+
+ testname = test_basename(test);
+ //fprintf(stderr, "branch %s test %s\n", branch, test);
+
+ branch_get_next_commit_and_test(branch, &commit, testname, &age);
+ free(testname);
+
+ if (!*ret_branch || age < best_age) {
+ free(*ret_branch);
+ free(*ret_commit);
+ free(*ret_test);
+
+ *ret_branch = strdup(branch);
+ *ret_test = strdup(test);
+ *ret_commit = commit;
+ best_age = age;
+ }
+ }
+
+ if (!*ret_branch)
+ die("Nothing found");
+
+ fclose(branches);
+ free(line);
+}
+
+void usage(void)
+{
+ puts("get-test-job: get a test job and create lockfile");
+ exit(EXIT_SUCCESS);
+}
+
+int main(int argc, char *argv[])
+{
+ char *branch, *commit, *test, *testname;
+ bool created;
+ int opt;
+
+ while ((opt = getopt(argc, argv, "b:o:")) != -1) {
+ switch (opt) {
+ case 'b':
+ branches_to_test = strdup(optarg);
+ break;
+ case 'o':
+ outdir = strdup(optarg);
+ break;
+ case 'h':
+ usage();
+ exit(EXIT_SUCCESS);
+ case '?':
+ usage();
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ if (!branches_to_test || !outdir)
+ die("required argument missing");
+
+ do {
+ get_best_branch_commit_test(&branch, &commit, &test);
+
+ //fprintf(stderr, "got %s %s %s\n", branch, commit, test);
+
+ 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;
+
+ free(commitdir);
+ free(lockfile);
+ } while (!created);
+
+ printf("%s %s %s\n", branch, commit, test);
+}