ww: put selected toolchain first in test PATH
This commit is contained in:
@@ -16,6 +16,7 @@
|
||||
#include <fcntl.h>
|
||||
#include <libgen.h>
|
||||
#include <limits.h>
|
||||
#include <stdint.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#ifndef PATH_MAX
|
||||
@@ -82,6 +83,71 @@ run_argv(const char *prog, char *const argv[])
|
||||
return 1;
|
||||
}
|
||||
|
||||
extern char **environ;
|
||||
|
||||
struct test_environment {
|
||||
char **values;
|
||||
char *path;
|
||||
};
|
||||
|
||||
/* Pinned cmd/go appends PATH=$GOROOT/bin:$PATH to each test command and
|
||||
* os/exec keeps the appended duplicate. The selected WW driver's sibling
|
||||
* directory is the local toolchain-bin analogue. Build tools retain the
|
||||
* caller's environment; only the test binary receives this array. */
|
||||
static int
|
||||
make_test_environment(const char *toolbin, struct test_environment *out)
|
||||
{
|
||||
const char *oldpath = getenv("PATH");
|
||||
if (oldpath == NULL) oldpath = "";
|
||||
size_t dirn = strlen(toolbin), oldn = strlen(oldpath);
|
||||
if (oldn > SIZE_MAX - 7 || dirn > SIZE_MAX - oldn - 7) return -1;
|
||||
size_t pathn = 5 + dirn + (oldn != 0 ? 1 + oldn : 0);
|
||||
char *path = malloc(pathn + 1);
|
||||
if (path == NULL) return -1;
|
||||
memcpy(path, "PATH=", 5);
|
||||
memcpy(path + 5, toolbin, dirn);
|
||||
size_t at = 5 + dirn;
|
||||
if (oldn != 0) {
|
||||
path[at++] = ':';
|
||||
memcpy(path + at, oldpath, oldn);
|
||||
at += oldn;
|
||||
}
|
||||
path[at] = '\0';
|
||||
|
||||
size_t nenv = 0;
|
||||
while (environ[nenv] != NULL) {
|
||||
if (nenv == SIZE_MAX - 2) { free(path); return -1; }
|
||||
nenv++;
|
||||
}
|
||||
if (nenv > SIZE_MAX / sizeof(char *) - 2) {
|
||||
free(path);
|
||||
return -1;
|
||||
}
|
||||
char **values = calloc(nenv + 2, sizeof *values);
|
||||
if (values == NULL) { free(path); return -1; }
|
||||
size_t n = 0;
|
||||
int inserted = 0;
|
||||
for (size_t i = 0; i < nenv; i++) {
|
||||
if (strncmp(environ[i], "PATH=", 5) == 0) {
|
||||
if (!inserted) { values[n++] = path; inserted = 1; }
|
||||
} else {
|
||||
values[n++] = environ[i];
|
||||
}
|
||||
}
|
||||
if (!inserted) values[n++] = path;
|
||||
values[n] = NULL;
|
||||
out->values = values;
|
||||
out->path = path;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
free_test_environment(struct test_environment *env)
|
||||
{
|
||||
free(env->values);
|
||||
free(env->path);
|
||||
}
|
||||
|
||||
/* run_test_bin — exec the built test binary with an optional name-filter
|
||||
* pattern as argv[1] (lib/test run() reads it via os.args). fork+execv
|
||||
* (not system()) so glob metacharacters in the pattern reach the binary
|
||||
@@ -91,14 +157,28 @@ run_argv(const char *prog, char *const argv[])
|
||||
static int
|
||||
run_test_bin(const char *bin, const char *pattern)
|
||||
{
|
||||
char toolbin[PATH_MAX];
|
||||
if (realpath(self_dir, toolbin) == NULL) {
|
||||
fputs("ww: cannot prepare test environment\n", stderr);
|
||||
return -1;
|
||||
}
|
||||
struct test_environment env = {0};
|
||||
if (make_test_environment(toolbin, &env) != 0) {
|
||||
fputs("ww: cannot prepare test environment\n", stderr);
|
||||
return -1;
|
||||
}
|
||||
pid_t pid = fork();
|
||||
if (pid < 0) { perror("ww: fork"); return -1; }
|
||||
if (pid < 0) {
|
||||
perror("ww: fork");
|
||||
free_test_environment(&env);
|
||||
return -1;
|
||||
}
|
||||
if (pid == 0) {
|
||||
char *xargv[3];
|
||||
xargv[0] = (char *)bin;
|
||||
if (pattern) { xargv[1] = (char *)pattern; xargv[2] = NULL; }
|
||||
else { xargv[1] = NULL; }
|
||||
execv(bin, xargv);
|
||||
execve(bin, xargv, env.values);
|
||||
perror("ww: exec");
|
||||
_exit(127);
|
||||
}
|
||||
@@ -108,6 +188,7 @@ run_test_bin(const char *bin, const char *pattern)
|
||||
* test PASS. */
|
||||
pid_t got;
|
||||
do { got = waitpid(pid, &status, 0); } while (got < 0 && errno == EINTR);
|
||||
free_test_environment(&env);
|
||||
if (got < 0) { perror("ww: waitpid"); return -1; }
|
||||
if (WIFEXITED(status)) return WEXITSTATUS(status);
|
||||
return 1;
|
||||
|
||||
Reference in New Issue
Block a user