build: make executable and test roots package actions

This commit is contained in:
2026-08-12 22:00:02 +09:00
parent fc4bde703e
commit 1724ea086f
11 changed files with 722 additions and 364 deletions

View File

@@ -8,19 +8,16 @@ package sepbuild_test;
//
// sepbuild (#46 commit-3) — build_one_sep END-TO-END on the real lib
// chain root -> os -> {rt,time} (transitive-closure discovery + topo):
// build+run exit 7 both stages; {time,rt,os}.wwi + __root.s
// materialize (#69: the root is compiled without -I, so no
// __root.wwi); per-package .s/.wwi/.unit.ww and the final binary
// build+run exit 7 both stages; {time,rt,os,__root}.wwi/.a
// materialize; per-package .s/.wwi/.a/.unit.ww and the final binary
// byte-id cs vs ww; every .unit.ww is the package's own sorted source
// set; `ww run` routes through the same sole sep path (exit 7 both
// stages).
//
// seproot (#69 BUG-1) — a ROOT whose `export fn use(a: *t)` names an
// unexported local `type t` builds (exit 37 both stages) because the
// root is compiled WITHOUT the -I .wwi-producer flag: __root.wwi must
// NOT exist; replaying the driver's own __root.unit.ww plus c.wwi
// through w6c/w6c_ww with -I must REJECT (the isolated bug) while -c
// -o alone must accept; __root.s carries the exported fn.
// seproot — a ROOT whose `export fn use(a: *t)` reaches an unexported
// local `type t` builds and emits a deterministic self-contained .wwi/.a.
// The private type is carried as compiler export data without `export`, and
// an importing source still cannot qualify `main.t`.
//
// sepstructdef (#70 BUG-2) — a dep exporting aggregate-init defs
// (struct-lit + array-lit) sep-builds and links (exit 20 both
@@ -91,29 +88,25 @@ fn samefile(label: str, what: str, a: str, b: str) void = {
s += 1;
};
// discovery/topo: the transitive package set materialized. #69: the
// root emits no .wwi (compiled without -I); its .s stands in.
// discovery/topo: every reachable package action materialized.
let pkgs: []str = ["time", "rt", "os", "__root"];
let i: i32 = 0;
for (i < pkgs.len) {
let suffix: str = ".wwi";
if (testenv.same(pkgs[i], "__root")) { suffix = ".s"; };
if (!testenv.exists(strings.concat(td, "/prog.cs.sepwork/",
pkgs[i], suffix))) {
fail("sepbuild", strings.concat(pkgs[i], suffix,
pkgs[i], ".wwi")) || !testenv.exists(strings.concat(td,
"/prog.cs.sepwork/", pkgs[i], ".a"))) {
fail("sepbuild", strings.concat(pkgs[i], ".wwi/.a",
" missing (discovery/topo)"));
};
i += 1;
};
// cs==ww (rule 10): per-package artifacts + the final binary
let sufs: []str = [".s", ".wwi", ".unit.ww"];
let sufs: []str = [".s", ".wwi", ".a", ".unit.ww"];
let p: i32 = 0;
for (p < pkgs.len) {
let k: i32 = 0;
for (k < sufs.len) {
if (testenv.same(pkgs[p], "__root")
&& testenv.same(sufs[k], ".wwi")) { k += 1; continue; };
samefile("sepbuild", strings.concat(pkgs[p], sufs[k]),
strings.concat(td, "/prog.cs.sepwork/", pkgs[p], sufs[k]),
strings.concat(td, "/prog.ww.sepwork/", pkgs[p], sufs[k]));
@@ -171,15 +164,13 @@ fn samefile(label: str, what: str, a: str, b: str) void = {
s += 1;
};
// cs==ww; the root's .wwi is intentionally absent (asserted below)
// cs==ww for the complete package artifacts, including the root archive.
let pkgs: []str = ["c", "__root"];
let sufs: []str = [".s", ".wwi", ".unit.ww"];
let sufs: []str = [".s", ".wwi", ".a", ".unit.ww"];
let p: i32 = 0;
for (p < pkgs.len) {
let k: i32 = 0;
for (k < sufs.len) {
if (testenv.same(pkgs[p], "__root")
&& testenv.same(sufs[k], ".wwi")) { k += 1; continue; };
samefile("seproot", strings.concat(pkgs[p], sufs[k]),
strings.concat(td, "/prog.cs.sepwork/", pkgs[p], sufs[k]),
strings.concat(td, "/prog.ww.sepwork/", pkgs[p], sufs[k]));
@@ -190,38 +181,51 @@ fn samefile(label: str, what: str, a: str, b: str) void = {
samefile("seproot", "the final binary",
strings.concat(td, "/prog.cs"), strings.concat(td, "/prog.ww"));
// the fix: the root is compiled WITHOUT -I, so no __root.wwi
// The reachable private nominal is compiler data, not a public source name.
let s2: i32 = 0;
for (s2 < 2) {
if (testenv.exists(strings.concat(td, "/prog.", tags[s2],
".sepwork/__root.wwi"))) {
let rootiface: str = strings.concat(td, "/prog.", tags[s2],
".sepwork/__root.wwi");
let ifacebytes: str = testenv.readfile(rootiface);
if (!testenv.has(ifacebytes, "type t = struct { v: i32 }")
|| testenv.has(ifacebytes, "export type t")
|| !testenv.has(ifacebytes, "export fn use(a: *t) i32;")) {
fail("seproot", strings.concat(drvs[s2],
" produced __root.wwi (-I still passed for the root)"));
" did not carry a private reachable type as compiler data"));
};
s2 += 1;
};
// replay the pre-fix invocation on the driver's own __root.unit.ww:
// with -I the export-check FIRES (the isolated bug); without it the
// post-fix invocation accepts. Both compilers.
// Replay the package compile with -I: both compilers accept and emit the
// same self-contained export. A source importer cannot name its private t.
let unit: str = strings.concat(td, "/prog.cs.sepwork/__root.unit.ww");
let ciface: str = strings.concat(td, "/prog.cs.sepwork/c.wwi");
let consumer: str = strings.concat(td, "/consumer.ww");
testenv.writefile(consumer, strings.concat(
"package consumer;\n",
"import main;\n",
"fn forbidden(v: *main.t) void = {};\n"));
let comps: []str = ["w6c", "w6c_ww"];
let c: i32 = 0;
for (c < 2) {
let wwi: str = strings.concat(td, "/nv.", comps[c], ".wwi");
let asmf: str = strings.concat(td, "/nv.", comps[c], ".s");
let rav: []str = [testenv.driver(comps[c]), "-c", "--import", "c",
ciface, "-I", wwi, "-o", asmf, unit];
if (runcode(td, strings.concat("nvI_", comps[c]), rav) == 0) {
fail("seproot", strings.concat(comps[c], " -c -I accepted the ",
"root export-over-unexported-type (vacuous gate)"));
let rav: []str = [testenv.driver(comps[c]), "--entry", "-c",
"--import", "c", ciface, "-I", wwi, "-o", asmf, unit];
if (runcode(td, strings.concat("reexport_", comps[c]), rav) != 0) {
fail("seproot", strings.concat(comps[c],
" rejected the self-contained root export"));
};
let aav: []str = [testenv.driver(comps[c]), "-c", "--import", "c",
ciface, "-o", asmf, unit];
if (runcode(td, strings.concat("nvO_", comps[c]), aav) != 0) {
fail("seproot", strings.concat(comps[c], " -c -o (no -I) ",
"rejected the root unit (post-fix invocation)"));
let rejectav: []str = [testenv.driver(comps[c]), "-c", "--import",
"main", wwi, "-o", asmf, consumer];
let reject: testenv.commandout;
testenv.runcommand(td, td, strings.concat("private_", comps[c]),
rejectav, tmo(), &reject);
if (reject.termination != exec.termination.EXIT || reject.code == 0
|| !testenv.has(reject.stderr,
"package 'main' has no exported declaration 't'")) {
fail("seproot", strings.concat(comps[c],
" exposed the compiler-private type to source importers"));
};
c += 1;
};