test: cover directory-only import resolution
Exercise both real drivers with an earlier single-file decoy and a later canonical package directory, exact sorted unit ownership, direct export composition, deterministic package artifacts, transitive linking, stable file-only rejection, and a directory-package test import.
This commit is contained in:
2
Makefile
2
Makefile
@@ -371,7 +371,7 @@ BYTEID_WW_TARGETS = $(BYTEID_WW_TESTS:%=wwtest/%)
|
||||
SEP_WW_TESTS = test/sep/sepbuild_test.ww test/sep/sepimport_test.ww \
|
||||
test/sep/seplink_test.ww test/sep/sepscratch_test.ww \
|
||||
test/sep/septest_test.ww test/sep/m3sep_test.ww \
|
||||
test/sep/localbuild_test.ww
|
||||
test/sep/localbuild_test.ww test/sep/importdir_test.ww
|
||||
SEP_WW_TARGETS = $(SEP_WW_TESTS:%=wwtest/%)
|
||||
# Ww-native lib env/OS arranger observers: the env contracts of the
|
||||
# lib/os and lib/dirs suites (getenv cohorts, XDG cohorts, the dirs
|
||||
|
||||
163
test/sep/importdir_test.ww
Normal file
163
test/sep/importdir_test.ww
Normal file
@@ -0,0 +1,163 @@
|
||||
package importdir_test;
|
||||
|
||||
import os;
|
||||
import os.exec;
|
||||
import strings;
|
||||
import testenv;
|
||||
import time;
|
||||
|
||||
fn fail(why: str) void = {
|
||||
let m: str = strings.concat("importdir FAIL: ", why, "\n");
|
||||
os.write(2, m.ptr, m.len: u64);
|
||||
assert(false);
|
||||
};
|
||||
|
||||
fn mkdir(path: str) void = { assert(os.mkdir(path, 493) == 0); };
|
||||
|
||||
fn command(td: str, name: str, argv: []str,
|
||||
out: *testenv.commandout) void = {
|
||||
testenv.runcommand(td, td, name, argv,
|
||||
(240i64 * (time.second: i64)): time.duration, out);
|
||||
};
|
||||
|
||||
fn expectcode(td: str, name: str, argv: []str, want: i32) void = {
|
||||
let out: testenv.commandout;
|
||||
command(td, name, argv, &out);
|
||||
if (out.termination != exec.termination.EXIT || out.code != want) {
|
||||
fail(strings.concat(name, " exit != expected: ", out.stderr));
|
||||
};
|
||||
};
|
||||
|
||||
fn samefile(a: str, b: str, why: str) void = {
|
||||
if (!testenv.same(testenv.readfile(a), testenv.readfile(b))) { fail(why); };
|
||||
};
|
||||
|
||||
@test fn import_is_directory_package() void = {
|
||||
let td: str = testenv.fresh();
|
||||
let early: str = strings.concat(td, "/early");
|
||||
let late: str = strings.concat(td, "/late");
|
||||
let earlyex: str = strings.concat(early, "/example");
|
||||
let lateex: str = strings.concat(late, "/example");
|
||||
let base: str = strings.concat(lateex, "/base");
|
||||
let bar: str = strings.concat(lateex, "/bar");
|
||||
let foo: str = strings.concat(lateex, "/foo");
|
||||
let app: str = strings.concat(td, "/app");
|
||||
let checks: str = strings.concat(td, "/checks");
|
||||
mkdir(early); mkdir(late); mkdir(earlyex); mkdir(lateex);
|
||||
mkdir(base); mkdir(bar); mkdir(foo); mkdir(app); mkdir(checks);
|
||||
|
||||
let decoy: str = strings.concat(
|
||||
"package foo;\n// DECOY_FILE\n",
|
||||
"export fn value() i32 = { return 99; };\n");
|
||||
let basesrc: str = strings.concat(
|
||||
"package base;\n",
|
||||
"export fn value() i32 = { return 37; };\n");
|
||||
let barsrc: str = strings.concat(
|
||||
"package bar;\nimport example.base;\n",
|
||||
"export fn value() i32 = { return base.value() + 3; };\n");
|
||||
let afoosrc: str = strings.concat(
|
||||
"package foo;\n// A_OWNED\n",
|
||||
"fn localdelta() i32 = { return 2; };\n");
|
||||
let zfoosrc: str = strings.concat(
|
||||
"package foo;\nimport example.bar;\n// Z_OWNED\n",
|
||||
"export fn value() i32 = { return bar.value() + localdelta(); };\n");
|
||||
let appsrc: str = strings.concat(
|
||||
"package main;\nimport example.foo;\n",
|
||||
"fn main() i32 = { return foo.value(); };\n");
|
||||
testenv.writefile(strings.concat(earlyex, "/foo.ww"), decoy);
|
||||
testenv.writefile(strings.concat(base, "/base.ww"), basesrc);
|
||||
testenv.writefile(strings.concat(bar, "/bar.ww"), barsrc);
|
||||
testenv.writefile(strings.concat(foo, "/a.ww"), afoosrc);
|
||||
testenv.writefile(strings.concat(foo, "/z.ww"), zfoosrc);
|
||||
testenv.writefile(strings.concat(app, "/main.ww"), appsrc);
|
||||
|
||||
let stems: []str = [strings.concat(td, "/c1"),
|
||||
strings.concat(td, "/c2"), strings.concat(td, "/ww")];
|
||||
let drivers: []str = ["ww", "ww", "ww_ww"];
|
||||
let tags: []str = ["c1", "c2", "ww"];
|
||||
let i: i32 = 0;
|
||||
for (i < stems.len) {
|
||||
let av: []str = [testenv.driver(drivers[i]), "build",
|
||||
"-I", early, "-I", late, "-o", stems[i], app];
|
||||
expectcode(td, strings.concat("build_", tags[i]), av, 0);
|
||||
let rav: []str = [stems[i]];
|
||||
expectcode(td, strings.concat("run_", tags[i]), rav, 42);
|
||||
i += 1;
|
||||
};
|
||||
|
||||
let cwork: str = strings.concat(stems[0], ".sepwork/");
|
||||
let cwork2: str = strings.concat(stems[1], ".sepwork/");
|
||||
let wwork: str = strings.concat(stems[2], ".sepwork/");
|
||||
let bariface: str = testenv.readfile(strings.concat(cwork, "example.bar.wwi"));
|
||||
let fooiface: str = testenv.readfile(strings.concat(cwork, "example.foo.wwi"));
|
||||
let foounit: str = testenv.readfile(strings.concat(cwork,
|
||||
"example.foo.unit.ww"));
|
||||
let wantfoo: str = strings.concat("//ww:module example.bar\n", bariface,
|
||||
"\n//ww:module-reset example.foo\n", afoosrc,
|
||||
"\n//ww:module-reset example.foo\n", zfoosrc, "\n");
|
||||
if (!testenv.same(foounit, wantfoo)
|
||||
|| testenv.has(foounit, "DECOY_FILE")) {
|
||||
fail("foo unit is not its sorted, owned source set plus direct bar export");
|
||||
};
|
||||
let wantroot: str = strings.concat("//ww:module example.foo\n", fooiface,
|
||||
"\n//ww:module-reset\n", appsrc, "\n");
|
||||
if (!testenv.same(wantroot, testenv.readfile(strings.concat(cwork,
|
||||
"__root.unit.ww")))) {
|
||||
fail("root unit is not direct-foo-only");
|
||||
};
|
||||
let keys: []str = ["example.base", "example.bar", "example.foo"];
|
||||
let suffixes: []str = [".wwi", ".a"];
|
||||
i = 0;
|
||||
for (i < keys.len) {
|
||||
let j: i32 = 0;
|
||||
for (j < suffixes.len) {
|
||||
let rel: str = strings.concat(keys[i], suffixes[j]);
|
||||
samefile(strings.concat(cwork, rel), strings.concat(cwork2, rel),
|
||||
strings.concat(rel, " changed across clean C builds"));
|
||||
samefile(strings.concat(cwork, rel), strings.concat(wwork, rel),
|
||||
strings.concat(rel, " differs between stages"));
|
||||
j += 1;
|
||||
};
|
||||
i += 1;
|
||||
};
|
||||
samefile(stems[0], stems[1], "C executables are not deterministic");
|
||||
samefile(stems[0], stems[2], "C/WW executables differ");
|
||||
|
||||
let cerr: testenv.commandout;
|
||||
let werr: testenv.commandout;
|
||||
let cav: []str = [testenv.driver("ww"), "build", "-I", early,
|
||||
"-o", strings.concat(td, "/bad-c"), app];
|
||||
let wav: []str = [testenv.driver("ww_ww"), "build", "-I", early,
|
||||
"-o", strings.concat(td, "/bad-w"), app];
|
||||
command(td, "file_only_c", cav, &cerr);
|
||||
command(td, "file_only_w", wav, &werr);
|
||||
if (cerr.termination != exec.termination.EXIT || cerr.code == 0
|
||||
|| werr.termination != exec.termination.EXIT || werr.code == 0
|
||||
|| !testenv.same(cerr.stderr, werr.stderr)
|
||||
|| !testenv.has(cerr.stderr, "cannot find package example.foo")
|
||||
|| !testenv.has(cerr.stderr, strings.concat(app, "/main.ww:"))) {
|
||||
fail("file-only import rejection is not stable and package-attributed");
|
||||
};
|
||||
|
||||
testenv.writefile(strings.concat(checks, "/checks.ww"),
|
||||
"package checks;\nexport fn ready() bool = { return true; };\n");
|
||||
testenv.writefile(strings.concat(checks, "/checks_test.ww"), strings.concat(
|
||||
"package checks;\nimport example.foo;\n",
|
||||
"@test fn directory_import() void = { assert(foo.value() == 42); };\n"));
|
||||
let testbins: []str = [strings.concat(td, "/test-c"),
|
||||
strings.concat(td, "/test-w")];
|
||||
i = 0;
|
||||
for (i < 2) {
|
||||
let tav: []str = [testenv.driver(drivers[i * 2]), "test", "-c",
|
||||
"-I", early, "-I", late, "-o", testbins[i], checks];
|
||||
expectcode(td, strings.concat("test_build_", tags[i * 2]), tav, 0);
|
||||
let trav: []str = [testbins[i]];
|
||||
expectcode(td, strings.concat("test_run_", tags[i * 2]), trav, 0);
|
||||
i += 1;
|
||||
};
|
||||
samefile(testbins[0], testbins[1], "directory-test binaries differ");
|
||||
samefile(strings.concat(testbins[0], ".sepwork/example.foo.a"),
|
||||
strings.concat(testbins[1], ".sepwork/example.foo.a"),
|
||||
"directory-test dependency archives differ");
|
||||
testenv.clean(td);
|
||||
};
|
||||
Reference in New Issue
Block a user