322 lines
11 KiB
Plaintext
322 lines
11 KiB
Plaintext
package sepimport_test;
|
|
|
|
// Import/namespace-resolution observers on the sep drivers, both
|
|
// stages. Ports of the retired native carriers
|
|
// test/wcc/989_coloimport_sep.c, 989_depmain_sep.c, 989_declns_sep.c
|
|
// and 989_slttypepref_run.c; every assertion preserved.
|
|
//
|
|
// coloimport (#98) — a co-located `_test` entry must not shadow the
|
|
// dir-package it imports under `ww test`: the two-pass locate_import
|
|
// walk resolves `import widget` to the DIR-package on a later -I
|
|
// entry, not the same-named sibling FILE on the srcd entry. Exit 0
|
|
// both stages (pre-fix w6c rejects `package widget does not match
|
|
// import path gadget`), widget.{unit.ww,wwi} registered in .sepwork,
|
|
// and every .s/.wwi byte-id cs vs ww (rule 10).
|
|
//
|
|
// depmain (#99) — an IMPORTED dir-package's non-exported `fn main`
|
|
// mangles on its import path (aa.bb.main / cc.main) instead of
|
|
// emitting a bare `TEXT main` that collides with the root entry;
|
|
// EXACTLY one column-0 `TEXT main,` across the whole sep build.
|
|
//
|
|
// declns (#23/#30 modfn leg) — a value-namespace `fn aa` coexists
|
|
// with an imported MODULE aa (exit 6 = aa() + aa.helper()); the _vbu
|
|
// layout flips decl order and must stay byte-identical on
|
|
// {aa.s,aa.wwi,__root.s} (silent order-dependence in the SK_USE/value
|
|
// promote is the regression); __root.s carries BOTH
|
|
// `CALL aa.helper(SB)` and `CALL main.aa(SB)`.
|
|
//
|
|
// slttypepref (#58/#50 c1) — scopelookuptype must prefer the current
|
|
// module's SK_TYPE when a param shadows a type leaf two modules both
|
|
// export: xb's `size(invalid)` resolves xb's !i64 (exit 8), never
|
|
// xa's !i8, on both stages, shadow and noshadow rows. The
|
|
// two-DIRECTORY tree is load-bearing (a single-file twin risks a
|
|
// different scope-install order — E3-C1 retarget note in the
|
|
// carrier); each (row,driver) rebuilds a fresh tree.
|
|
//
|
|
// Dropped C machinery, not assertions: the ww_ww-absent skip gate
|
|
// (the Make target declares both drivers) and the per-path
|
|
// unlink/rmdir accounting (testenv.clean asserts the removal).
|
|
|
|
import os;
|
|
import os.exec;
|
|
import strings;
|
|
import testenv;
|
|
import time;
|
|
|
|
fn fail(label: str, why: str) void = {
|
|
let m: str = strings.concat("sepimport FAIL: ", label, " -- ", why,
|
|
"\n");
|
|
os.write(2, m.ptr, m.len: u64);
|
|
assert(false);
|
|
};
|
|
|
|
fn tmo() time.duration = {
|
|
return (240i64 * (time.second: i64)): time.duration;
|
|
};
|
|
|
|
// -1 encodes an abnormal (non-EXIT) termination, never a valid code.
|
|
fn runcode(dir: str, name: str, argv: []str) i32 = {
|
|
let co: testenv.commandout;
|
|
testenv.runcommand(dir, dir, name, argv, tmo(), &co);
|
|
if (co.termination != exec.termination.EXIT) { return -1; };
|
|
return co.code;
|
|
};
|
|
|
|
fn cmpsepwork(label: str, csdir: str, wwdir: str) void = {
|
|
if (!testenv.isdir(csdir)) { fail(label, "no cs sepwork"); };
|
|
let names: []str = testenv.listdir(csdir);
|
|
let seen: i32 = 0;
|
|
let i: i32 = 0;
|
|
for (i < names.len) {
|
|
if (strings.hassuffix(names[i], ".s")
|
|
|| strings.hassuffix(names[i], ".wwi")
|
|
|| strings.hassuffix(names[i], ".a")) {
|
|
seen += 1;
|
|
if (!testenv.same(
|
|
testenv.readfile(strings.concat(csdir, "/", names[i])),
|
|
testenv.readfile(strings.concat(wwdir, "/", names[i])))) {
|
|
fail(label, strings.concat("cs!=ww for ", names[i],
|
|
" (rule 10)"));
|
|
};
|
|
};
|
|
i += 1;
|
|
};
|
|
// an existing-but-empty sepwork would pass the loop vacuously
|
|
if (seen == 0) { fail(label, "no package artifacts in cs sepwork"); };
|
|
};
|
|
|
|
@test fn coloimport() void = {
|
|
let td: str = testenv.fresh();
|
|
let inc: str = strings.concat(testenv.repo(), "/test/wcc/data/colo98");
|
|
let entry: str = strings.concat(inc, "/widget/widget_test.ww");
|
|
let drvs: []str = ["ww", "ww_ww"];
|
|
let tags: []str = ["cs", "ww"];
|
|
let i: i32 = 0;
|
|
for (i < 2) {
|
|
let prog: str = strings.concat(td, "/widget.", tags[i], ".bin");
|
|
let av: []str = [testenv.driver(drvs[i]), "test", "-I", inc,
|
|
"-o", prog, entry];
|
|
if (runcode(td, strings.concat("colo_", tags[i]), av) != 0) {
|
|
fail("coloimport", strings.concat("`ww test` exit != 0 on ",
|
|
drvs[i], " (import folded to the sibling file?)"));
|
|
};
|
|
i += 1;
|
|
};
|
|
let csdir: str = strings.concat(td, "/widget.cs.bin.sepwork");
|
|
let wwdir: str = strings.concat(td, "/widget.ww.bin.sepwork");
|
|
if (!testenv.exists(strings.concat(csdir, "/widget.unit.ww"))) {
|
|
fail("coloimport", strings.concat("widget.unit.ww missing (import ",
|
|
"folded to the sibling file, not the dir-package)"));
|
|
};
|
|
if (!testenv.exists(strings.concat(csdir, "/widget.wwi"))) {
|
|
fail("coloimport", "widget.wwi missing");
|
|
};
|
|
cmpsepwork("coloimport", csdir, wwdir);
|
|
testenv.clean(td);
|
|
};
|
|
|
|
// column-0 anchored `TEXT main,` labels across every .s under `dir`;
|
|
// the leading '\n' prepend also counts a file-leading label.
|
|
fn countbaremain(dir: str) i32 = {
|
|
let names: []str = testenv.listdir(dir);
|
|
let n: i32 = 0;
|
|
let i: i32 = 0;
|
|
for (i < names.len) {
|
|
if (strings.hassuffix(names[i], ".s")) {
|
|
let body: str = strings.concat("\n",
|
|
testenv.readfile(strings.concat(dir, "/", names[i])));
|
|
n += testenv.occurrences(body, "\nTEXT main,");
|
|
};
|
|
i += 1;
|
|
};
|
|
return n;
|
|
};
|
|
|
|
fn depmainrow(label: str, entry: str, want: i32, deps: str,
|
|
mangled: str) void = {
|
|
let td: str = testenv.fresh();
|
|
let src: str = strings.concat(testenv.repo(), "/", entry);
|
|
let drvs: []str = ["ww", "ww_ww"];
|
|
let tags: []str = ["cs", "ww"];
|
|
let i: i32 = 0;
|
|
for (i < 2) {
|
|
let prog: str = strings.concat(td, "/", label, ".", tags[i],
|
|
".bin");
|
|
let av: []str = [testenv.driver(drvs[i]), "build", "-o", prog,
|
|
src];
|
|
if (runcode(td, strings.concat("build_", tags[i]), av) != 0) {
|
|
fail(label, strings.concat(drvs[i], " build failed (bare-main ",
|
|
"collision -> w6l duplicate symbol?)"));
|
|
};
|
|
let rav: []str = [prog];
|
|
if (runcode(td, strings.concat("run_", tags[i]), rav) != want) {
|
|
fail(label, strings.concat(drvs[i],
|
|
" run-exit != the dep main's return"));
|
|
};
|
|
i += 1;
|
|
};
|
|
let csdir: str = strings.concat(td, "/", label, ".cs.bin.sepwork");
|
|
let wwdir: str = strings.concat(td, "/", label, ".ww.bin.sepwork");
|
|
if (!testenv.has(testenv.readfile(strings.concat(csdir, "/", deps)),
|
|
mangled)) {
|
|
fail(label, strings.concat(deps, " lacks `", mangled,
|
|
"` (dep main not mangled)"));
|
|
};
|
|
if (countbaremain(csdir) != 1) {
|
|
fail(label, strings.concat("bare `TEXT main,` count != 1 ",
|
|
"(only the root entry stays bare)"));
|
|
};
|
|
cmpsepwork(label, csdir, wwdir);
|
|
testenv.clean(td);
|
|
};
|
|
|
|
@test fn depmain_aabb() void = {
|
|
depmainrow("aabb", "test/wcc/data/depmain99/main.ww", 7,
|
|
"aa.bb.s", "TEXT aa.bb.main,");
|
|
};
|
|
|
|
@test fn depmain_cc() void = {
|
|
depmainrow("cc", "test/wcc/data/depmain99/main_cc.ww", 9,
|
|
"cc.s", "TEXT cc.main,");
|
|
};
|
|
|
|
@test fn declns() void = {
|
|
let td: str = testenv.fresh();
|
|
let lays: []str = ["modfn_coexist", "modfn_coexist_vbu"];
|
|
let labs: []str = ["coexist", "coexist_vbu"];
|
|
let drvs: []str = ["ww", "ww_ww"];
|
|
let tags: []str = ["cs", "ww"];
|
|
let l: i32 = 0;
|
|
for (l < 2) {
|
|
let s: i32 = 0;
|
|
for (s < 2) {
|
|
let prog: str = strings.concat(td, "/", labs[l], ".",
|
|
tags[s]);
|
|
let src: str = strings.concat(testenv.repo(),
|
|
"/test/wcc/data/", lays[l], "/main.ww");
|
|
let av: []str = [testenv.driver(drvs[s]), "build", "-o",
|
|
prog, src];
|
|
if (runcode(td, strings.concat("b_", labs[l], "_", tags[s]),
|
|
av) != 0) {
|
|
fail(labs[l], strings.concat(drvs[s], " build failed"));
|
|
};
|
|
let rav: []str = [prog];
|
|
if (runcode(td, strings.concat("r_", labs[l], "_", tags[s]),
|
|
rav) != 6) {
|
|
fail(labs[l], strings.concat(drvs[s],
|
|
" exit != 6 (coexistence mis-resolved)"));
|
|
};
|
|
s += 1;
|
|
};
|
|
l += 1;
|
|
};
|
|
|
|
// Both the dependency and raw explicit root emit complete package artifacts.
|
|
let parts: []str = ["aa.s", "aa.wwi", "aa.a", "aa.unit.ww",
|
|
"__root.s", "__root.wwi", "__root.a", "__root.unit.ww"];
|
|
|
|
// cs==ww (rule 10) per layout over the complete package-artifact table
|
|
let l2: i32 = 0;
|
|
for (l2 < 2) {
|
|
let p: i32 = 0;
|
|
for (p < parts.len) {
|
|
if (!testenv.same(
|
|
testenv.readfile(strings.concat(td, "/", labs[l2],
|
|
".cs.sepwork/", parts[p])),
|
|
testenv.readfile(strings.concat(td, "/", labs[l2],
|
|
".ww.sepwork/", parts[p])))) {
|
|
fail(labs[l2], strings.concat("cs!=ww for ", parts[p],
|
|
" (rule 10)"));
|
|
};
|
|
p += 1;
|
|
};
|
|
l2 += 1;
|
|
};
|
|
|
|
// cross-LAYOUT byte-id, same stage: decl-order independence of the
|
|
// SK_USE/value promote. `.unit.ww` embeds the differently ORDERED
|
|
// source, so the codegen claim is tested on .s/.wwi only.
|
|
let oparts: []str = ["aa.s", "aa.wwi", "__root.s"];
|
|
let t: i32 = 0;
|
|
for (t < 2) {
|
|
let p: i32 = 0;
|
|
for (p < oparts.len) {
|
|
if (!testenv.same(
|
|
testenv.readfile(strings.concat(td, "/coexist.",
|
|
tags[t], ".sepwork/", oparts[p])),
|
|
testenv.readfile(strings.concat(td, "/coexist_vbu.",
|
|
tags[t], ".sepwork/", oparts[p])))) {
|
|
fail("declns", strings.concat("vbu!=non-vbu for ",
|
|
oparts[p], " (", tags[t],
|
|
") -- silent decl-order dependence"));
|
|
};
|
|
p += 1;
|
|
};
|
|
t += 1;
|
|
};
|
|
|
|
// non-vacuity: the two namespaces resolve to DISTINCT symbols
|
|
let t2: i32 = 0;
|
|
for (t2 < 2) {
|
|
let rs: str = testenv.readfile(strings.concat(td, "/coexist.",
|
|
tags[t2], ".sepwork/__root.s"));
|
|
if (!testenv.has(rs, "CALL\taa.helper(SB)")) {
|
|
fail("declns", strings.concat("__root.s (", tags[t2],
|
|
") lacks module-qualified `CALL aa.helper(SB)`"));
|
|
};
|
|
if (!testenv.has(rs, "CALL\tmain.aa(SB)")) {
|
|
fail("declns", strings.concat("__root.s (", tags[t2],
|
|
") lacks local-fn `CALL main.aa(SB)`"));
|
|
};
|
|
t2 += 1;
|
|
};
|
|
testenv.clean(td);
|
|
};
|
|
|
|
// fresh two-directory tree per (row,driver); relative build with the
|
|
// tree as cwd (canonical dir-package build, binary lands in cwd).
|
|
fn sltbuild(drv: str, param: str) i32 = {
|
|
let dir: str = testenv.fresh();
|
|
assert(os.mkdir(strings.concat(dir, "/xa"), 493) == 0);
|
|
assert(os.mkdir(strings.concat(dir, "/xb"), 493) == 0);
|
|
testenv.writefile(strings.concat(dir, "/xa/xa.ww"), strings.concat(
|
|
"package xa;\n",
|
|
"export type invalid = !i8;\n"));
|
|
testenv.writefile(strings.concat(dir, "/xb/xb.ww"), strings.concat(
|
|
"package xb;\n",
|
|
"import xa;\n",
|
|
"export type invalid = !i64;\n",
|
|
"export fn f(", param,
|
|
": i32) i64 = { return size(invalid): i64; };\n"));
|
|
testenv.writefile(strings.concat(dir, "/root.ww"), strings.concat(
|
|
"package main;\n",
|
|
"import xb;\n",
|
|
"import xa;\n",
|
|
"fn main() int = { return xb.f(0): int; };\n"));
|
|
let bav: []str = [testenv.driver(drv), "build", "root.ww"];
|
|
let brc: i32 = runcode(dir, "build", bav);
|
|
if (brc != 0) {
|
|
testenv.clean(dir);
|
|
return -1;
|
|
};
|
|
let rav: []str = [strings.concat(dir, "/root")];
|
|
let got: i32 = runcode(dir, "run", rav);
|
|
testenv.clean(dir);
|
|
return got;
|
|
};
|
|
|
|
fn sltrow(label: str, param: str, want: i32) void = {
|
|
let gc: i32 = sltbuild("ww", param);
|
|
if (gc != want) { fail(label, "cstage exit != want (size of the wrong module's type)"); };
|
|
let gw: i32 = sltbuild("ww_ww", param);
|
|
if (gw != gc) {
|
|
fail(label, strings.concat("cs != ww exit (scopelookuptype ",
|
|
"mod-preference divergence -- #58/#50 c1)"));
|
|
};
|
|
if (gw != want) { fail(label, "wwstage exit != want"); };
|
|
};
|
|
|
|
@test fn slt_shadow() void = { sltrow("shadow", "invalid", 8); };
|
|
|
|
@test fn slt_noshadow() void = { sltrow("noshadow", "x", 8); };
|