Semver check tests: the first-release probe's cwd and blob size are pinned, and assembly-less packages read no tags' trees

Also defines the PE fixture before the tests that use it, so a filtered run no
longer reaches it before initialization.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
Meta Vens 2026-10-03 09:53:17 +02:00
commit 8c9faf06c6

View file

@ -411,6 +411,30 @@ function tagWithFiles(dir, tag, files) {
commitAndTag(dir, tag);
}
// A PE image written byte by byte. A managed assembly's CLI header is data directory 14; a
// native DLL has none.
function peImage({ plus = true, directories = 16, cli = null } = {}) {
const pe = 0x40;
const optionalSize = (plus ? 112 : 96) + directories * 8;
const bytes = Buffer.alloc(pe + 24 + optionalSize);
bytes.writeUInt16LE(0x5a4d, 0);
bytes.writeUInt32LE(pe, 0x3c);
bytes.writeUInt32LE(0x00004550, pe);
bytes.writeUInt16LE(plus ? 0x8664 : 0x14c, pe + 4);
bytes.writeUInt16LE(optionalSize, pe + 20);
const optional = pe + 24;
bytes.writeUInt16LE(plus ? 0x20b : 0x10b, optional);
const dirs = optional + (plus ? 112 : 96);
bytes.writeUInt32LE(directories, dirs - 4);
if (cli) {
bytes.writeUInt32LE(cli.rva, dirs + 14 * 8);
bytes.writeUInt32LE(cli.size, dirs + 14 * 8 + 4);
}
return bytes;
}
const CLI = { rva: 0x2000, size: 0x48 };
test("CLI: a mistyped declared prefix of a Unity package is refused, because a tag under another prefix tracks its managed assembly", () => {
// The real entries of CultMath and cultlib, each released once under its real prefix, then
// the declaration misspelled. Nothing is measured: the refusal comes from git.
@ -465,6 +489,31 @@ test("CLI: only a managed assembly under the declared assemblies directory prove
});
});
test("CLI: the first-release probe reads the repository of --cwd and a blob of any size, and reads no tree for a package without assemblies", () => {
const elsewhere = mkdtempSync(join(tmpdir(), "cultlib-semver-elsewhere-"));
try {
withTempGitRepo((dir) => {
declare(dir, { widget: { ...WIDGET, assemblies: PLUGINS } });
// a managed assembly larger than the default 1 MiB buffer of a child process
tagWithFiles(dir, "other-v1.0.0", { [`${PLUGINS}/Big.dll`]: Buffer.concat([peImage({ cli: CLI }), Buffer.alloc(2 << 20)]) });
writeChangelog(dir, "1.0.0");
const junk = join(dir, "junk.dll");
writeFileSync(junk, "junk");
const refused = runCheckerExpectFailure(dir, [...widgetArgs("1.0.0"), "--api-built", junk], { processCwd: elsewhere });
assert.ok(refused.includes(`other-v1.0.0 tracks the managed assembly ${PLUGINS}/Big.dll`), refused);
});
withTempGitRepo((dir) => {
commitAndTag(dir, "other-v1.0.0");
writeFileSync(join(dir, ".git", "refs", "tags", "other-v2.0.0"), "1".repeat(40) + "\n");
writeChangelog(dir, "1.0.0");
// an unreadable tag matters only to a package whose assemblies it could have shipped
assert.match(runChecker(dir, widgetArgs("1.0.0")), /first release \(1\.0\.0\)/);
});
} finally {
rmSync(elsewhere, { recursive: true, force: true });
}
});
test("CLI: a package with no assemblies is a first release when no tag of its own prefix exists, whatever other tags track", () => {
withTempGitRepo((dir) => {
declare(dir, { widget: { ...WIDGET, changelog: "pkg/CHANGELOG.md" } });
@ -816,30 +865,6 @@ test("measured: an assembly tracked in a subdirectory is measured, and is a brea
});
});
// A PE image written byte by byte. A managed assembly's CLI header is data directory 14; a
// native DLL has none.
function peImage({ plus = true, directories = 16, cli = null } = {}) {
const pe = 0x40;
const optionalSize = (plus ? 112 : 96) + directories * 8;
const bytes = Buffer.alloc(pe + 24 + optionalSize);
bytes.writeUInt16LE(0x5a4d, 0);
bytes.writeUInt32LE(pe, 0x3c);
bytes.writeUInt32LE(0x00004550, pe);
bytes.writeUInt16LE(plus ? 0x8664 : 0x14c, pe + 4);
bytes.writeUInt16LE(optionalSize, pe + 20);
const optional = pe + 24;
bytes.writeUInt16LE(plus ? 0x20b : 0x10b, optional);
const dirs = optional + (plus ? 112 : 96);
bytes.writeUInt32LE(directories, dirs - 4);
if (cli) {
bytes.writeUInt32LE(cli.rva, dirs + 14 * 8);
bytes.writeUInt32LE(cli.size, dirs + 14 * 8 + 4);
}
return bytes;
}
const CLI = { rva: 0x2000, size: 0x48 };
test("isManagedAssembly: a non-empty CLI header makes an assembly managed, nothing else does", () => {
assert.equal(isManagedAssembly(peImage({ cli: CLI })), true);
assert.equal(isManagedAssembly(peImage({ plus: false, cli: CLI })), true);