206 lines
8.2 KiB
Plaintext
206 lines
8.2 KiB
Plaintext
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 appidentity: str = testenv.localpackageidentity(app, "main");
|
|
let foounit: str = testenv.readfile(strings.concat(cwork,
|
|
"example.foo.unit.ww"));
|
|
let wantfoo: str = strings.concat("//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")
|
|
|| testenv.has(foounit, "//ww:module ")) {
|
|
fail("foo unit is not exactly its sorted, owned source set");
|
|
};
|
|
let wantroot: str = strings.concat("//ww:module-reset ", appidentity,
|
|
"\n", appsrc,
|
|
"\n");
|
|
if (!testenv.same(wantroot, testenv.readfile(strings.concat(cwork,
|
|
appidentity, ".unit.ww")))) {
|
|
fail("root unit is not exactly its owned source");
|
|
};
|
|
let keys: []str = ["example.base", "example.bar", "example.foo",
|
|
appidentity];
|
|
let suffixes: []str = [".unit.ww", ".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");
|
|
|
|
// The same canonical directory is now observed as an imported dependency,
|
|
// a literal root, an explicit logical root, an equivalent path spelling,
|
|
// and a symlink spelling. Every route must publish the one example.foo
|
|
// action with byte-identical owner unit, export, and archive.
|
|
let fooalias: str = strings.concat(td, "/foo-alias");
|
|
assert(os.symlink(foo, fooalias) == 0);
|
|
let rootouts: []str = [strings.concat(td, "/foo-root-c"),
|
|
strings.concat(td, "/foo-root-w"),
|
|
strings.concat(td, "/foo-logical-c"),
|
|
strings.concat(td, "/foo-logical-w"),
|
|
strings.concat(td, "/foo-equivalent-c"),
|
|
strings.concat(td, "/foo-equivalent-w"),
|
|
strings.concat(td, "/foo-relative-c"),
|
|
strings.concat(td, "/foo-relative-w"),
|
|
strings.concat(td, "/foo-alias-c"),
|
|
strings.concat(td, "/foo-alias-w")];
|
|
let rootdrivers: []str = ["ww", "ww_ww", "ww", "ww_ww", "ww",
|
|
"ww_ww", "ww", "ww_ww", "ww", "ww_ww"];
|
|
let roottags: []str = ["literal-c", "literal-w", "logical-c",
|
|
"logical-w", "equivalent-c", "equivalent-w", "relative-c",
|
|
"relative-w", "alias-c", "alias-w"];
|
|
let roottargets: []str = [foo, foo, "example.foo", "example.foo",
|
|
strings.concat(foo, "/../foo"), strings.concat(foo, "/../foo"),
|
|
"late/example/foo", "late/example/foo", fooalias, fooalias];
|
|
i = 0;
|
|
for (i < rootouts.len) {
|
|
let rav: []str = [testenv.driver(rootdrivers[i]), "build", "-p",
|
|
"-I", early, "-I", late, "-o", rootouts[i], roottargets[i]];
|
|
expectcode(td, strings.concat("foo_root_", roottags[i]), rav, 0);
|
|
let rw: str = strings.concat(rootouts[i], ".sepwork/");
|
|
let rsuffixes: []str = [".unit.ww", ".wwi", ".a"];
|
|
let ri: i32 = 0;
|
|
for (ri < rsuffixes.len) {
|
|
let artifact: str = strings.concat("example.foo", rsuffixes[ri]);
|
|
samefile(strings.concat(cwork, artifact), strings.concat(rw, artifact),
|
|
"canonical foo action changed across root spellings");
|
|
ri += 1;
|
|
};
|
|
i += 1;
|
|
};
|
|
|
|
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);
|
|
};
|