ww: run directory tests from package source

This commit is contained in:
2026-08-20 15:58:47 +09:00
parent 3d596388bb
commit 5f75fcb113

View File

@@ -210,7 +210,7 @@ fn pkgappenddiscovered(st: *pkgdiscover, path: str) bool = {
};
// Preserve the caller's toolchain environment while pinning the locale and
// temporary directory used by the current build plan or test product.
// temporary directory used by the current build plan.
fn toolenv(tmpdir: str, out: *[]str) bool = {
let inherited: []str = os.getenvs();
if (inherited.len > PKG_COUNT_MAX - 2) {
@@ -243,6 +243,73 @@ fn toolenv(tmpdir: str, out: *[]str) bool = {
return true;
};
fn pkgfreeownedstr(value: str) void = {
if (value.ptr != nil && value.len != 0) {
os.free(value.ptr: *void, value.len: u64);
};
};
fn pkgfreestrs(values: []str) void = {
if (values.ptr != nil && values.cap != 0) {
os.free(values.ptr: *void,
(values.cap: u64) * (size(str): u64));
};
};
// Go's AppendPWD appends, then os/exec keeps the last duplicate value. WW's
// executor preserves duplicates, so discard earlier exact PWD entries here.
fn runenv(tmpdir: str, pwd: str, out: *[]str, tmpowned: *str,
pwdowned: *str) bool = {
let inherited: []str = os.getenvs();
if (inherited.len > PKG_COUNT_MAX - 3) {
pkgputln(os.STDERR_FILENO,
"wwtest package: package graph is too large");
return false;
};
let allocation: ([]str | nomem) = pkgallocstrs(inherited.len + 3);
let env: []str;
match (allocation) {
case let value: []str => env = value;
case nomem => {
pkgputln(os.STDERR_FILENO, "wwtest package: out of memory");
return false;
};
};
let i: i32 = 0;
for (i < inherited.len) {
if (!strings.hasprefix(inherited[i], "TMPDIR=")
&& !strings.hasprefix(inherited[i], "LC_ALL=")
&& !strings.hasprefix(inherited[i], "PWD=")) {
append(env, inherited[i]);
};
i += 1;
};
append(env, "LC_ALL=C");
let tmpenv: str;
if (!pkgstring(&tmpenv, "TMPDIR=", tmpdir)) {
pkgfreestrs(env);
return false;
};
let pwdenv: str;
if (!pkgstring(&pwdenv, "PWD=", pwd)) {
pkgfreeownedstr(tmpenv);
pkgfreestrs(env);
return false;
};
append(env, tmpenv);
append(env, pwdenv);
*out = env;
*tmpowned = tmpenv;
*pwdowned = pwdenv;
return true;
};
fn freerunenv(env: []str, tmpowned: str, pwdowned: str) void = {
pkgfreeownedstr(tmpowned);
pkgfreeownedstr(pwdowned);
pkgfreestrs(env);
};
fn pkgwrite(fd: i32, s: str) bool = {
let r: (i64 | os.oserror) = os.writeall(fd, s.ptr, s.len: u64);
match (r) {
@@ -1453,25 +1520,37 @@ fn pkgstartrun(g: *pkggroup, filters: []str, timeoutarg: str,
};
append(ra, g.bin);
let packagearg: str;
if (!pkgstring(&packagearg, "-package=", g.pkg)) { return false; };
if (!pkgstring(&packagearg, "-package=", g.pkg)) {
pkgfreestrs(ra);
return false;
};
append(ra, packagearg);
if (list) { append(ra, "-list"); };
if (timeoutarg.len != 0) { append(ra, timeoutarg); };
let i: i32 = 0;
for (i < filters.len) { append(ra, filters[i]); i += 1; };
let env: []str;
if (!toolenv(g.root, &env)) { return false; };
let tmpowned: str;
let pwdowned: str;
if (!runenv(g.root, g.dir, &env, &tmpowned, &pwdowned)) {
pkgfreeownedstr(packagearg);
pkgfreestrs(ra);
return false;
};
let rcmd: exec.command;
rcmd.path = g.bin;
rcmd.argv = ra;
rcmd.env = env;
rcmd.dir = "";
rcmd.dir = g.dir;
rcmd.stdoutpath = g.runout;
rcmd.stderrpath = g.runerr;
rcmd.deadline.sec = 0i64;
rcmd.deadline.nsec = 0i64;
rcmd.grace = 0i64: time.duration;
exec.start(h, &rcmd);
freerunenv(env, tmpowned, pwdowned);
pkgfreeownedstr(packagearg);
pkgfreestrs(ra);
return true;
};
@@ -1758,8 +1837,7 @@ export fn packagecommand(args: []str) int = {
pkgusage();
return 2;
};
// -o names the -c artifact; a plain run always executes from the
// temp root, so a caller-owned name has nothing to name.
// A non-compile run leaves no caller-owned artifact for -o to name.
if (outname.len != 0 && !compileonly) {
pkgputln(os.STDERR_FILENO, "wwtest package: -o needs -c");
return 2;