ww test: allow -c with persistent workdirs
This commit is contained in:
@@ -6286,11 +6286,11 @@ transaction prevents partial sibling publication and canonical result emission
|
|||||||
order remains unchanged. Direct invocation of a retained binary continues to
|
order remains unchanged. Direct invocation of a retained binary continues to
|
||||||
inherit caller cwd, environment, and separate standard descriptors.
|
inherit caller cwd, environment, and separate standard descriptors.
|
||||||
|
|
||||||
`-o` can accompany `-w`: unchanged semantic actions are reused, changed source
|
`-c` and `-o` can accompany `-w`: the workdir owns only semantic actions while
|
||||||
invalidates the applicable test actions, the always-run link refreshes the
|
the invocation/output path owns only the retained copy. Unchanged actions are
|
||||||
private runnable and retained copy, and the test still runs. This is build
|
reused, changed source invalidates the applicable test actions, and the
|
||||||
reuse, not a result cache. `-c` retains its established incompatibility with
|
always-run link refreshes the private runnable and retained copy. Only `-c`
|
||||||
`-w`; this slice does not invent persistent compile-only ownership.
|
suppresses execution. This is build reuse, not a result cache.
|
||||||
|
|
||||||
No persisted byte schema changed. Build workdir format remains `18`, test
|
No persisted byte schema changed. Build workdir format remains `18`, test
|
||||||
workdir format remains `19`, and semantic storage remains `3`.
|
workdir format remains `19`, and semantic storage remains `3`.
|
||||||
|
|||||||
@@ -665,6 +665,9 @@ destinations and removes temporary stages and invocation-created output
|
|||||||
prefixes. Test execution starts only after that transaction commits, so a
|
prefixes. Test execution starts only after that transaction commits, so a
|
||||||
runtime failure leaves an explicitly retained binary. A no-test product
|
runtime failure leaves an explicitly retained binary. A no-test product
|
||||||
publishes no binary and does not create a directory solely for one.
|
publishes no binary and does not create a directory solely for one.
|
||||||
|
`-w` may persist the unchanged semantic actions for either `-c` or running
|
||||||
|
retention without changing publication identity or introducing a test-result
|
||||||
|
cache.
|
||||||
|
|
||||||
When `ww test` executes a directory-owned product, the child process working
|
When `ww test` executes a directory-owned product, the child process working
|
||||||
directory is that product's canonical absolute physical package source
|
directory is that product's canonical absolute physical package source
|
||||||
|
|||||||
@@ -482,11 +482,12 @@ path as the one command-global semantic-action store; neither pattern spelling
|
|||||||
nor package-group name derives a persistent subdirectory. The delegated driver
|
nor package-group name derives a persistent subdirectory. The delegated driver
|
||||||
may create a missing store only after graph and request preflight, and rolls
|
may create a missing store only after graph and request preflight, and rolls
|
||||||
back newly created empty prefixes if later setup fails. Every reuse decision
|
back newly created empty prefixes if later setup fails. Every reuse decision
|
||||||
stays with the driver's content-identity contract above. `-w` and test `-c` do
|
stays with the driver's content-identity contract above. Test `-c` may use the
|
||||||
not mix — the coordinator rejects the combination rather than guess which
|
same store: the workdir owns semantic actions and the invocation/output path
|
||||||
artifact tree the caller owns. `test-library` uses exactly this: one
|
owns the separately staged retained executable. The `test-library` route uses
|
||||||
`ww test -j $(JOBS) -w out/wwbuild/wwtest-lib lib/...` line owns library
|
the same command-global store contract: one `ww test -j $(JOBS) -w
|
||||||
behavior (measured: 2.3s cold, 1.0s warm at
|
out/wwbuild/wwtest-lib lib/...` line owns library behavior (measured: 2.3s
|
||||||
|
cold, 1.0s warm at
|
||||||
`-j 4`, vs 4.7s for the retired 59-target per-file fan-out).
|
`-j 4`, vs 4.7s for the retired 59-target per-file fan-out).
|
||||||
|
|
||||||
`test/lang` currently uses one package per source file, so its complete gate
|
`test/lang` currently uses one package per source file, so its complete gate
|
||||||
|
|||||||
@@ -1853,15 +1853,6 @@ export fn packagecommand(args: []str) int = {
|
|||||||
pkgusage();
|
pkgusage();
|
||||||
return 2;
|
return 2;
|
||||||
};
|
};
|
||||||
// -c suppresses execution and requests a caller-visible binary. Keep it
|
|
||||||
// separate from -w until compile-only persistent-action ownership is wired;
|
|
||||||
// -o without -c already permits a retained copy beside a persistent store.
|
|
||||||
if (workroot.len != 0 && compileonly && !buildonly) {
|
|
||||||
pkgputln(os.STDERR_FILENO,
|
|
||||||
"wwtest package: -w conflicts with -c");
|
|
||||||
return 2;
|
|
||||||
};
|
|
||||||
|
|
||||||
let ds: pkgdiscover;
|
let ds: pkgdiscover;
|
||||||
let emptypaths: []str;
|
let emptypaths: []str;
|
||||||
ds.paths = emptypaths;
|
ds.paths = emptypaths;
|
||||||
|
|||||||
@@ -9215,18 +9215,26 @@ fn cwdwritedata(dir: str, label: str) void = {
|
|||||||
(30i64 * (time.second: i64)): time.duration, &outc);
|
(30i64 * (time.second: i64)): time.duration, &outc);
|
||||||
expectexit(&outc, 0);
|
expectexit(&outc, 0);
|
||||||
assert(same(outc.stdout, seq));
|
assert(same(outc.stdout, seq));
|
||||||
// -c publishes caller-owned artifacts; a persistent workdir is a
|
// The retained executable is separate from the persistent action store, so
|
||||||
// different ownership contract — the coordinator rejects the mix.
|
// -c can suppress execution while reusing the same complete graph.
|
||||||
|
let wcbin: str = strings.concat(root, "/tree-wc-c.test");
|
||||||
|
let wwbin: str = strings.concat(root, "/tree-wc-ww.test");
|
||||||
let wcc: []str = [driver("ww"), "test", "-c", "-w", wdroot,
|
let wcc: []str = [driver("ww"), "test", "-c", "-w", wdroot,
|
||||||
"-I", tree, spec];
|
"-o", wcbin, "-I", tree, strings.concat(tree, "/alpha")];
|
||||||
let wcw: []str = [driver("ww_ww"), "test", "-c", "-w", wdroot,
|
let wcw: []str = [driver("ww_ww"), "test", "-c", "-w", wdroot,
|
||||||
"-I", tree, spec];
|
"-o", wwbin, "-I", tree, strings.concat(tree, "/alpha")];
|
||||||
runcommand(root, "tree-wc-c", wcc, time.second, &outc);
|
runcommand(root, "tree-wc-c", wcc,
|
||||||
runcommand(root, "tree-wc-ww", wcw, time.second, &outw);
|
(30i64 * (time.second: i64)): time.duration, &outc);
|
||||||
expectexit(&outc, 2);
|
runcommand(root, "tree-wc-ww", wcw,
|
||||||
expectexit(&outw, 2);
|
(30i64 * (time.second: i64)): time.duration, &outw);
|
||||||
|
expectexit(&outc, 0);
|
||||||
|
expectexit(&outw, 0);
|
||||||
|
assert(outc.stdout.len == 0 && outc.stderr.len == 0);
|
||||||
|
assert(outw.stdout.len == 0 && outw.stderr.len == 0);
|
||||||
|
assert(os.exists(wcbin) && os.exists(wwbin));
|
||||||
|
assert(same(readfile(wcbin), readfile(wwbin)));
|
||||||
assert(same(outc.stderr, outw.stderr));
|
assert(same(outc.stderr, outw.stderr));
|
||||||
assert(has(outc.stderr, "wwtest package: -w conflicts with -c\n"));
|
clean(wcbin); clean(wwbin);
|
||||||
|
|
||||||
let bare: str = strings.concat(root, "/bare");
|
let bare: str = strings.concat(root, "/bare");
|
||||||
let barez: str = strings.concat(root, "/zz-bare");
|
let barez: str = strings.concat(root, "/zz-bare");
|
||||||
@@ -12566,42 +12574,60 @@ fn runtimepath(relative: str) str = {
|
|||||||
if (si == 0) { failurebytes = readfile(failurebin); }
|
if (si == 0) { failurebytes = readfile(failurebin); }
|
||||||
else { assert(same(failurebytes, readfile(failurebin))); };
|
else { assert(same(failurebytes, readfile(failurebin))); };
|
||||||
|
|
||||||
// -w keeps semantic actions persistent while -o remains a presentation
|
// -w keeps semantic actions persistent while -c and -o remain execution
|
||||||
// copy. Unchanged input reuses actions; changed input replaces the copy.
|
// and presentation policy. Compile-only can cold-build and invalidate;
|
||||||
|
// an unchanged running request reuses those actions and the same bytes.
|
||||||
rewritefile(persisttest, persistbase);
|
rewritefile(persisttest, persistbase);
|
||||||
let persistwork: str = strings.concat(root, "/persist-work-", tags[si]);
|
let persistwork: str = strings.concat(root, "/persist-work-", tags[si]);
|
||||||
let persistbin: str = strings.concat(root, "/persist.test");
|
let persistcompilebin: str = strings.concat(root, "/persist-compile-",
|
||||||
if (os.exists(persistbin)) { clean(persistbin); };
|
tags[si], ".test");
|
||||||
|
let persistbin: str = strings.concat(root, "/persist-run-", tags[si],
|
||||||
|
".test");
|
||||||
rewritefile(ctrace, ""); rewritefile(ltrace, "");
|
rewritefile(ctrace, ""); rewritefile(ltrace, "");
|
||||||
|
let persistcompileav: []str = [driver(stages[si]), "test", "-c",
|
||||||
|
"-w", persistwork, "-I", suite, "-o", persistcompilebin,
|
||||||
|
persist];
|
||||||
let persistav: []str = [driver(stages[si]), "test", "-w",
|
let persistav: []str = [driver(stages[si]), "test", "-w",
|
||||||
persistwork, "-I", suite, "-o", persistbin, persist];
|
persistwork, "-I", suite, "-o", persistbin, persist];
|
||||||
runcommandenvdir(root, strings.concat("publish-persist-cold-", tags[si]),
|
runcommandenvdir(root, strings.concat("publish-persist-cold-c-", tags[si]),
|
||||||
|
persistcompileav, env, root,
|
||||||
|
(120i64 * (time.second: i64)): time.duration, &out);
|
||||||
|
expectexit(&out, 0);
|
||||||
|
assert(out.stdout.len == 0 && out.stderr.len == 0);
|
||||||
|
assert(readfile(ctrace).len != 0);
|
||||||
|
let basebytes: str = readfile(persistcompilebin);
|
||||||
|
if (si == 0) { persistbasebytes = strings.dup(basebytes); }
|
||||||
|
else { assert(same(persistbasebytes, basebytes)); };
|
||||||
|
rewritefile(ctrace, ""); rewritefile(ltrace, "");
|
||||||
|
runcommandenvdir(root, strings.concat("publish-persist-warm-run-", tags[si]),
|
||||||
persistav, env, root,
|
persistav, env, root,
|
||||||
(120i64 * (time.second: i64)): time.duration, &out);
|
(120i64 * (time.second: i64)): time.duration, &out);
|
||||||
expectexit(&out, 0);
|
expectexit(&out, 0);
|
||||||
assert(has(out.stdout, "persistent_base ... ok\n"));
|
assert(has(out.stdout, "persistent_base ... ok\n"));
|
||||||
let basebytes: str = readfile(persistbin);
|
|
||||||
if (si == 0) { persistbasebytes = strings.dup(basebytes); }
|
|
||||||
else { assert(same(persistbasebytes, basebytes)); };
|
|
||||||
rewritefile(ctrace, ""); rewritefile(ltrace, "");
|
|
||||||
runcommandenvdir(root, strings.concat("publish-persist-warm-", tags[si]),
|
|
||||||
persistav, env, root,
|
|
||||||
(120i64 * (time.second: i64)): time.duration, &out);
|
|
||||||
expectexit(&out, 0);
|
|
||||||
assert(readfile(ctrace).len == 0);
|
assert(readfile(ctrace).len == 0);
|
||||||
assert(same(basebytes, readfile(persistbin)));
|
assert(same(basebytes, readfile(persistbin)));
|
||||||
rewritefile(persisttest, persistchanged);
|
rewritefile(persisttest, persistchanged);
|
||||||
rewritefile(ctrace, ""); rewritefile(ltrace, "");
|
rewritefile(ctrace, ""); rewritefile(ltrace, "");
|
||||||
runcommandenvdir(root, strings.concat("publish-persist-change-", tags[si]),
|
runcommandenvdir(root, strings.concat("publish-persist-change-c-", tags[si]),
|
||||||
persistav, env, root,
|
persistcompileav, env, root,
|
||||||
(120i64 * (time.second: i64)): time.duration, &out);
|
(120i64 * (time.second: i64)): time.duration, &out);
|
||||||
expectexit(&out, 0);
|
expectexit(&out, 0);
|
||||||
assert(has(out.stdout, "persistent_changed ... ok\n"));
|
assert(out.stdout.len == 0 && out.stderr.len == 0);
|
||||||
assert(readfile(ctrace).len != 0);
|
assert(readfile(ctrace).len != 0);
|
||||||
let changedbytes: str = readfile(persistbin);
|
let changedbytes: str = readfile(persistcompilebin);
|
||||||
assert(!same(basebytes, changedbytes));
|
assert(!same(basebytes, changedbytes));
|
||||||
if (si == 0) { persistchangedbytes = strings.dup(changedbytes); }
|
if (si == 0) { persistchangedbytes = strings.dup(changedbytes); }
|
||||||
else { assert(same(persistchangedbytes, changedbytes)); };
|
else { assert(same(persistchangedbytes, changedbytes)); };
|
||||||
|
rewritefile(ctrace, ""); rewritefile(ltrace, "");
|
||||||
|
runcommandenvdir(root, strings.concat("publish-persist-change-run-",
|
||||||
|
tags[si]), persistav, env, root,
|
||||||
|
(120i64 * (time.second: i64)): time.duration, &out);
|
||||||
|
expectexit(&out, 0);
|
||||||
|
assert(has(out.stdout, "persistent_changed ... ok\n"));
|
||||||
|
assert(readfile(ctrace).len == 0);
|
||||||
|
assert(same(changedbytes, readfile(persistbin)));
|
||||||
|
assert(!os.exists(strings.concat(persistcompilebin, ".new")));
|
||||||
|
assert(!os.exists(strings.concat(persistbin, ".new")));
|
||||||
assert(!directoryhasnew(persistwork));
|
assert(!directoryhasnew(persistwork));
|
||||||
si += 1;
|
si += 1;
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user