ww: test sources are *_test.ww only (Go contract)
Go compiles only _test.go files as tests; discovery now keys on the
_test.ww suffix alone. The line-leading-@test compatibility allowance
(noncanonical filenames admitted as test sources) is removed from both
driver stages and the coordinator. An @test declaration outside a
*_test.ww file is rejected loudly ("@test declaration outside
*_test.ww", wording byte-identical cs/ww) instead of silently running
under compose or silently dropping in a non-T build (#6). Tree audit
found zero real carriers; the two allowance fixtures flip canonical
(dep_test.ww, widget_test.ww). New pins: direnum attest-noncanon
reject row (both-stage stderr parity) and the coordinator
noncanonical_attest_rejected package row.
This commit is contained in:
@@ -352,10 +352,10 @@ fn locateimport(dirs: *u8, name: *u8, namelen: u64,
|
||||
return nil;
|
||||
};
|
||||
|
||||
// Temporary compatibility for the repository's pre-underscore test sources:
|
||||
// a noncanonical filename is test-only only when its body contains a real
|
||||
// line-leading @test declaration. This is the wwstage twin of
|
||||
// cmd/ww/main.c:file_has_line_test.
|
||||
// Go's contract: only *_test.ww is a test source. A line-leading @test
|
||||
// declaration anywhere else would be silently dropped by a non-T build
|
||||
// (#6, the Hare model), so directory enumeration rejects it loudly.
|
||||
// This is the wwstage twin of cmd/ww/main.c:file_has_line_test.
|
||||
fn dirfileattest(dirpath: *u8, name: *u8) bool = {
|
||||
let path: *u8 = joinpath(dirpath, name);
|
||||
let fd: i32 = os.open(pathstr(path), os.flag.RDONLY, 0i32);
|
||||
@@ -393,20 +393,20 @@ fn dirfileattest(dirpath: *u8, name: *u8) bool = {
|
||||
return false;
|
||||
};
|
||||
|
||||
// Filter for production enumeration: keep `*.ww` minus canonical
|
||||
// `*_test.ww` and the explicit compatibility sources above. Returns
|
||||
// true to keep.
|
||||
fn dirfilekeep(dirpath: *u8, name: *u8, nlen: u64) bool = {
|
||||
// Classify a directory entry for production enumeration: 1 keep,
|
||||
// 0 skip (non-source or *_test.ww), -1 @test outside *_test.ww
|
||||
// (caller diagnoses and fails).
|
||||
fn dirfileclass(dirpath: *u8, name: *u8, nlen: u64) i32 = {
|
||||
// nlen<=3 guard kept: a bare ".ww" (len 3) is rejected here but
|
||||
// would pass strings.hassuffix(".ww"); preserves cstage parity.
|
||||
if (nlen <= 3u64) { return false; };
|
||||
if (nlen <= 3u64) { return 0; };
|
||||
let s: str;
|
||||
s.ptr = name;
|
||||
s.len = nlen: i32;
|
||||
if (!strings.hassuffix(s, ".ww")) { return false; };
|
||||
if (strings.hassuffix(s, "_test.ww")
|
||||
|| dirfileattest(dirpath, name)) { return false; };
|
||||
return true;
|
||||
if (!strings.hassuffix(s, ".ww")) { return 0; };
|
||||
if (strings.hassuffix(s, "_test.ww")) { return 0; };
|
||||
if (dirfileattest(dirpath, name)) { return -1; };
|
||||
return 1;
|
||||
};
|
||||
|
||||
// Byte-wise memcmp returning < 0, 0, > 0. Rule-10 byte-id requires
|
||||
@@ -429,10 +429,11 @@ fn bytecmp(a: *u8, alen: u64, b: *u8, blen: u64) i32 = {
|
||||
return 0;
|
||||
};
|
||||
|
||||
// enumeratedir — list production *.ww paths of `dirpath` (less canonical
|
||||
// and compatibility test sources), byte-sort. Returns
|
||||
// one exact pointer array of NUL-terminated full paths. This is the sole
|
||||
// directory-membership discovery path; the owning seppkg retains the list.
|
||||
// enumeratedir — list production *.ww paths of `dirpath` (less *_test.ww
|
||||
// test sources), byte-sort. A line-leading @test in any other source is
|
||||
// diagnosed here and returns -2. Returns one exact pointer array of
|
||||
// NUL-terminated full paths. This is the sole directory-membership
|
||||
// discovery path; the owning seppkg retains the list.
|
||||
fn enumeratedir(dirpath: *u8) (**u8, i32) = {
|
||||
let fd: i32 = os.open(pathstr(dirpath), os.flag.RDONLY, 0i32);
|
||||
if (fd < 0) { return nil: **u8, -1; };
|
||||
@@ -456,7 +457,15 @@ fn enumeratedir(dirpath: *u8) (**u8, i32) = {
|
||||
let reclen: u64 = blo + (bhi * 256u64);
|
||||
let nm: *u8 = buf.ptr + off + 19u64;
|
||||
let nl: u64 = cstrlen(nm);
|
||||
if (dirfilekeep(dirpath, nm, nl)) {
|
||||
let cls: i32 = dirfileclass(dirpath, nm, nl);
|
||||
if (cls < 0) {
|
||||
cerr("ww: ");
|
||||
cerr(pathstr(joinpath(dirpath, nm)));
|
||||
cerr(": @test declaration outside *_test.ww\n");
|
||||
os.close(fd);
|
||||
return nil: **u8, -2;
|
||||
};
|
||||
if (cls > 0) {
|
||||
if (n >= cap) {
|
||||
let ncap: i32 = cap * 2;
|
||||
let nn: []*u8 = alloc([], ncap: u64)!;
|
||||
@@ -1000,7 +1009,10 @@ fn seploadpkg(g: *sepgraph, pi: i32, searchpath: *u8) i32 = {
|
||||
sources, nsources = enumeratedir(g.pkg[pi].entry);
|
||||
g.pkg[pi].sources = sources;
|
||||
g.pkg[pi].nsources = nsources;
|
||||
if (g.pkg[pi].nsources < 0) {
|
||||
if (g.pkg[pi].nsources == -2) {
|
||||
// diagnosed in enumeratedir
|
||||
rc = -1;
|
||||
} else { if (g.pkg[pi].nsources < 0) {
|
||||
cerr("ww: cannot read directory ");
|
||||
cerr(pathstr(g.pkg[pi].entry));
|
||||
cerr("\n");
|
||||
@@ -1010,7 +1022,7 @@ fn seploadpkg(g: *sepgraph, pi: i32, searchpath: *u8) i32 = {
|
||||
cerr(pathstr(g.pkg[pi].entry));
|
||||
cerr(": directory contains no WW package sources\n");
|
||||
rc = -1;
|
||||
}; };
|
||||
}; }; };
|
||||
let i: i32 = 0;
|
||||
for (i < g.pkg[pi].nsources) {
|
||||
if (rc == 0) {
|
||||
|
||||
Reference in New Issue
Block a user