ww test: retain directory test binaries like Go
This commit is contained in:
@@ -1508,6 +1508,7 @@ type sepproduct = struct {
|
||||
internalpackage: *u8,
|
||||
externalpackage: *u8,
|
||||
status: *u8,
|
||||
publish: *u8,
|
||||
artifact: *u8,
|
||||
variant: i32,
|
||||
directoryproduct: bool,
|
||||
@@ -1520,6 +1521,7 @@ type sepproduct = struct {
|
||||
pxtest: i32,
|
||||
support: i32,
|
||||
stageout: *u8,
|
||||
stagepublish: *u8,
|
||||
stageiface: *u8,
|
||||
stagestatus: *u8,
|
||||
};
|
||||
@@ -5914,6 +5916,32 @@ fn copyfilestage(src: *u8, dst: *u8) i32 = {
|
||||
return 0;
|
||||
};
|
||||
|
||||
// BuildInstallFunc's linked-executable mode is 0777 filtered by umask. The
|
||||
// retained stage owns a distinct inode but exactly the temporary runnable's
|
||||
// bytes; the request transaction publishes them together below.
|
||||
fn copyexecutablestage(src: *u8, dst: *u8) i32 = {
|
||||
let in: i32 = os.open(pathstr(src), os.flag.RDONLY, 0i32);
|
||||
if (in < 0) { return -1; };
|
||||
let out: i32 = os.open(pathstr(dst),
|
||||
os.flag.WRONLY | os.flag.CREATE | os.flag.TRUNC, 511i32);
|
||||
if (out < 0) { os.close(in); return -1; };
|
||||
let buf: [65536]u8;
|
||||
let bad: bool = false;
|
||||
for (!bad) {
|
||||
let n: i64 = os.read(in, &buf[0], 65536u64);
|
||||
if (n < 0) { bad = true; break; };
|
||||
if (n == 0) { break; };
|
||||
match (os.writeall(out, &buf[0], n: u64)) {
|
||||
case let wrote: i64 => { if (wrote != n) { bad = true; }; };
|
||||
case let e: os.oserror => bad = true;
|
||||
};
|
||||
};
|
||||
if (os.close(in) != 0) { bad = true; };
|
||||
if (os.close(out) != 0) { bad = true; };
|
||||
if (bad) { os.remove(pathstr(dst)); return -1; };
|
||||
return 0;
|
||||
};
|
||||
|
||||
fn sepproductstagepath(dst: *u8) *u8 = {
|
||||
let path: *u8 = sepappendlit(dst, ".new");
|
||||
if (path != nil && cstrlen(path) + 1u64 > os.PATH_MAX: u64) {
|
||||
@@ -5945,12 +5973,16 @@ fn sepproductpathsoverlap(a: *u8, b: *u8) bool = {
|
||||
};
|
||||
|
||||
fn sepvalidateproductpathpair(a: *sepproduct, b: *sepproduct) i32 = {
|
||||
let ap: []*u8 = [nil, nil, a.stagestatus, a.stageout, a.stageiface];
|
||||
let bp: []*u8 = [nil, nil, b.stagestatus, b.stageout, b.stageiface];
|
||||
let ap: []*u8 = [nil, nil, nil, a.stagestatus, a.stageout,
|
||||
a.stagepublish, a.stageiface];
|
||||
let bp: []*u8 = [nil, nil, nil, b.stagestatus, b.stageout,
|
||||
b.stagepublish, b.stageiface];
|
||||
if (a.stagestatus != nil) { ap[0] = a.status; };
|
||||
if (a.stageout != nil) { ap[1] = a.out; };
|
||||
if (a.stagepublish != nil) { ap[2] = a.publish; };
|
||||
if (b.stagestatus != nil) { bp[0] = b.status; };
|
||||
if (b.stageout != nil) { bp[1] = b.out; };
|
||||
if (b.stagepublish != nil) { bp[2] = b.publish; };
|
||||
let i: i32 = 0;
|
||||
for (i < ap.len) {
|
||||
if (ap[i] != nil) {
|
||||
@@ -6037,6 +6069,11 @@ fn sepvalidaterequeststaging(g: *sepgraph, scratch: *u8, warm: bool,
|
||||
products[i].stagestatus, products[i].status);
|
||||
if (products[i].stagestatus == nil) { return -1; };
|
||||
};
|
||||
if (products[i].publish != nil && !products[i].notests) {
|
||||
products[i].stagepublish = sepprepareproductstage(
|
||||
products[i].stagepublish, products[i].publish);
|
||||
if (products[i].stagepublish == nil) { return -1; };
|
||||
};
|
||||
if (emitasm == 0) {
|
||||
let ownsoutput: bool = false;
|
||||
if (rootpackage) { ownsoutput = publishpackage != 0; }
|
||||
@@ -6413,7 +6450,8 @@ fn sepdiscardrequeststaging(g: *sepgraph, scratch: *u8, warm: bool,
|
||||
let producti: i32 = 0;
|
||||
for (producti < nproducts) {
|
||||
let paths: []*u8 = [products[producti].stageout,
|
||||
products[producti].stageiface, products[producti].stagestatus];
|
||||
products[producti].stagepublish, products[producti].stageiface,
|
||||
products[producti].stagestatus];
|
||||
let si: i32 = 0;
|
||||
for (si < paths.len) {
|
||||
if (paths[si] != nil) {
|
||||
@@ -6564,8 +6602,8 @@ fn sepfinishfail(entries: *[]septxnentry, n: i32) i32 = {
|
||||
fn sepfreeproductstaging(products: *sepproduct, nproducts: i32) void = {
|
||||
let i: i32 = 0;
|
||||
for (i < nproducts) {
|
||||
let paths: []*u8 = [products[i].stageout, products[i].stageiface,
|
||||
products[i].stagestatus];
|
||||
let paths: []*u8 = [products[i].stageout, products[i].stagepublish,
|
||||
products[i].stageiface, products[i].stagestatus];
|
||||
let k: i32 = 0;
|
||||
for (k < paths.len) {
|
||||
if (paths[k] != nil) {
|
||||
@@ -6574,6 +6612,7 @@ fn sepfreeproductstaging(products: *sepproduct, nproducts: i32) void = {
|
||||
k += 1;
|
||||
};
|
||||
products[i].stageout = nil;
|
||||
products[i].stagepublish = nil;
|
||||
products[i].stageiface = nil;
|
||||
products[i].stagestatus = nil;
|
||||
i += 1;
|
||||
@@ -6779,6 +6818,14 @@ fn sepfinishrequest(selfdir: *u8, l6: *u8, c6: *u8, a6: *u8,
|
||||
g.pkg[root].failed = true;
|
||||
return sepfinishfail(&entries, ntxn);
|
||||
};
|
||||
if (products[producti].publish != nil
|
||||
&& (products[producti].stagepublish == nil
|
||||
|| copyexecutablestage(products[producti].stageout,
|
||||
products[producti].stagepublish) != 0)) {
|
||||
cerrpath("ww: cannot stage test binary ",
|
||||
products[producti].publish, "\n");
|
||||
return sepfinishfail(&entries, ntxn);
|
||||
};
|
||||
if (sepstageproductstatus(&products[producti]) != 0) {
|
||||
cerr("ww: cannot stage package-test product\n");
|
||||
return sepfinishfail(&entries, ntxn);
|
||||
@@ -6860,6 +6907,11 @@ fn sepfinishrequest(selfdir: *u8, l6: *u8, c6: *u8, a6: *u8,
|
||||
products[producti].out)) {
|
||||
return sepfinishfail(&entries, ntxn);
|
||||
};
|
||||
if (products[producti].stagepublish != nil
|
||||
&& !septxnadd(&entries, &ntxn, products[producti].stagepublish,
|
||||
products[producti].publish)) {
|
||||
return sepfinishfail(&entries, ntxn);
|
||||
};
|
||||
if (products[producti].stageiface != nil) {
|
||||
let outiface: *u8 = sepappendlit(products[producti].out, ".wwi");
|
||||
if (outiface == nil
|
||||
@@ -7091,6 +7143,7 @@ fn buildonesepimpl(selfdir: *u8, src: *u8, entryisdir: i32,
|
||||
products[producti].ptest = -1;
|
||||
products[producti].pxtest = -1;
|
||||
products[producti].stageout = nil;
|
||||
products[producti].stagepublish = nil;
|
||||
products[producti].stageiface = nil;
|
||||
products[producti].stagestatus = nil;
|
||||
producti += 1;
|
||||
@@ -7443,6 +7496,10 @@ fn buildonesepimpl(selfdir: *u8, src: *u8, entryisdir: i32,
|
||||
&& validatecommandoutputpath(products[producti].out) < 0) {
|
||||
return 1;
|
||||
};
|
||||
if (products[producti].publish != nil
|
||||
&& validatecommandoutputpath(products[producti].publish) < 0) {
|
||||
return 1;
|
||||
};
|
||||
if (products[producti].status != nil
|
||||
&& validatecommandoutputpath(products[producti].status) < 0) {
|
||||
return 1;
|
||||
@@ -7563,10 +7620,17 @@ fn buildonesepimpl(selfdir: *u8, src: *u8, entryisdir: i32,
|
||||
let createdwork: sepcreateddirs;
|
||||
createdoutput.n = 0;
|
||||
createdwork.n = 0;
|
||||
let outputmode: i32 = 448;
|
||||
if (istest != 0) { outputmode = 511; };
|
||||
if (createoutputdir != nil
|
||||
&& sepmkdirsrecord(createoutputdir, 448, &createdoutput) != 0) {
|
||||
cerrpath("ww: cannot create build output directory ",
|
||||
createoutputdir, "\n");
|
||||
&& sepmkdirsrecord(createoutputdir, outputmode, &createdoutput) != 0) {
|
||||
if (istest != 0) {
|
||||
cerrpath("ww: cannot create test output directory ",
|
||||
createoutputdir, "\n");
|
||||
} else {
|
||||
cerrpath("ww: cannot create build output directory ",
|
||||
createoutputdir, "\n");
|
||||
};
|
||||
return 1;
|
||||
};
|
||||
if (warm && !workdirexists) {
|
||||
@@ -8095,6 +8159,7 @@ fn buildonesep(selfdir: *u8, src: *u8, entryisdir: i32,
|
||||
product.internalpackage = nil;
|
||||
product.externalpackage = nil;
|
||||
product.status = nil;
|
||||
product.publish = nil;
|
||||
product.artifact = nil;
|
||||
if (entryisdir == 0) {
|
||||
product.artifact = "__root\0".ptr;
|
||||
@@ -8910,8 +8975,8 @@ fn dotest(selfdir: *u8, argv: **u8, argc: i32, start: i32) i32 = {
|
||||
continue;
|
||||
};
|
||||
if (cstreqlit(p, "--ww-package-test")) {
|
||||
if (i + 8 >= argc) {
|
||||
cerr("ww test: --ww-package-test needs kind, package, production, internal, external, directory, output, and status\n");
|
||||
if (i + 9 >= argc) {
|
||||
cerr("ww test: --ww-package-test needs kind, package, production, internal, external, directory, output, publication, and status\n");
|
||||
return 2;
|
||||
};
|
||||
let kind: *u8 = argv[i + 1];
|
||||
@@ -8921,7 +8986,8 @@ fn dotest(selfdir: *u8, argv: **u8, argc: i32, start: i32) i32 = {
|
||||
let external: *u8 = argv[i + 5];
|
||||
let dir: *u8 = argv[i + 6];
|
||||
let output: *u8 = argv[i + 7];
|
||||
let status: *u8 = argv[i + 8];
|
||||
let publish: *u8 = argv[i + 8];
|
||||
let status: *u8 = argv[i + 9];
|
||||
let pn: u64 = cstrlen(name);
|
||||
let buildproduct: bool = cstreqlit(kind, "build");
|
||||
let testproduct: bool = cstreqlit(kind, "test");
|
||||
@@ -8931,6 +8997,7 @@ fn dotest(selfdir: *u8, argv: **u8, argc: i32, start: i32) i32 = {
|
||||
if ((!buildproduct && !testproduct)
|
||||
|| pn == 0u64
|
||||
|| dir[0u64] == 0u8 || output[0u64] == 0u8
|
||||
|| publish[0u64] == 0u8
|
||||
|| status[0u64] == 0u8
|
||||
|| (hasproduction && !cstreq(production, name))
|
||||
|| (hasinternal && !cstreq(internal, name))
|
||||
@@ -8938,9 +9005,12 @@ fn dotest(selfdir: *u8, argv: **u8, argc: i32, start: i32) i32 = {
|
||||
|| !strings.hasprefix(pathstr(external), pathstr(name))
|
||||
|| !cstrendswithlit(external, "_test")))
|
||||
|| (buildproduct && (!hasproduction
|
||||
|| hasinternal || hasexternal))
|
||||
|| hasinternal || hasexternal
|
||||
|| !cstreqlit(publish, "-")))
|
||||
|| (testproduct && !hasproduction
|
||||
&& !hasinternal && !hasexternal)) {
|
||||
&& !hasinternal && !hasexternal)
|
||||
|| (testproduct && !hasinternal && !hasexternal
|
||||
&& !cstreqlit(publish, "-"))) {
|
||||
cerr("ww test: invalid --ww-package-test product\n");
|
||||
return 2;
|
||||
};
|
||||
@@ -8956,6 +9026,8 @@ fn dotest(selfdir: *u8, argv: **u8, argc: i32, start: i32) i32 = {
|
||||
product.externalpackage = nil;
|
||||
if (hasexternal) { product.externalpackage = external; };
|
||||
product.status = status;
|
||||
product.publish = nil;
|
||||
if (!cstreqlit(publish, "-")) { product.publish = publish; };
|
||||
product.artifact = nil;
|
||||
product.variant = SEP_VARIANT_TEST_MAIN;
|
||||
if (buildproduct) { product.variant = SEP_VARIANT_PRODUCTION; };
|
||||
@@ -8974,7 +9046,7 @@ fn dotest(selfdir: *u8, argv: **u8, argc: i32, start: i32) i32 = {
|
||||
if (!sepreserveproducts(&products,
|
||||
products.len + 1)) { return 1; };
|
||||
append(products, product);
|
||||
i += 9;
|
||||
i += 10;
|
||||
continue;
|
||||
};
|
||||
if (p[1u64] == 73u8) { // '-I'
|
||||
@@ -9133,7 +9205,7 @@ fn dotest(selfdir: *u8, argv: **u8, argc: i32, start: i32) i32 = {
|
||||
cerr("ww test: invalid --ww-package-publish\n");
|
||||
return 2;
|
||||
};
|
||||
if (packagecreateoutputdir != nil && !packagebuild) {
|
||||
if (packagecreateoutputdir != nil && products.len == 0) {
|
||||
cerr("ww test: invalid private directory creation\n");
|
||||
return 2;
|
||||
};
|
||||
@@ -9220,12 +9292,8 @@ fn dotest(selfdir: *u8, argv: **u8, argc: i32, start: i32) i32 = {
|
||||
cerr("ww test: -S needs a single test file\n");
|
||||
return 2;
|
||||
};
|
||||
// -c -o forwards: the coordinator names the single
|
||||
// package's artifact and rejects a multi-package fan-out.
|
||||
if (outstem != nil && compileonly == 0) {
|
||||
cerr("ww test: -o needs -c for a package target\n");
|
||||
return 2;
|
||||
};
|
||||
// The coordinator independently wires -o retention and -c run
|
||||
// suppression after loading the complete package set.
|
||||
// -w forwards one caller-owned semantic-action store shared by
|
||||
// the complete selected package universe.
|
||||
return execpackagetests(selfdir, argv, argc, start,
|
||||
@@ -9273,10 +9341,6 @@ fn dotest(selfdir: *u8, argv: **u8, argc: i32, start: i32) i32 = {
|
||||
cerr("ww test: -S needs a single test file\n");
|
||||
return 2;
|
||||
};
|
||||
if (outstem != nil && compileonly == 0) {
|
||||
cerr("ww test: -o needs -c for a package target\n");
|
||||
return 2;
|
||||
};
|
||||
if (products.len != 0) {
|
||||
if (compileonly == 0) {
|
||||
cerr("ww test: package-test products need -c\n");
|
||||
|
||||
Reference in New Issue
Block a user