Skip to content

Commit dc3204f

Browse files
Assert the snapshot writer emits the header it was handed
The licence and the copyright holder are parameters of `LibRainDeploySnapshot` rather than constants inside it, so that deploy repos in other orgs get their own header in their own append-only `src/generated/<tag>/`. That freedom is only worth having if what is handed in is what comes out. The alias and released emitters each already assert their output byte for byte. The snapshot writer had no such assertion: the two values are strings of the same type in adjacent positions, so a call that swapped them compiles and writes a file carrying both, in the wrong tags. Every other test that reads a snapshot header reads the COMMITTED file, which is evidence about a generation that already happened rather than about what the writer emits now. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
1 parent db4e887 commit dc3204f

1 file changed

Lines changed: 68 additions & 0 deletions

File tree

test/src/lib/LibRainDeploySnapshot.t.sol

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -399,6 +399,74 @@ contract LibRainDeploySnapshotTest is Test {
399399
assertTrue(exists);
400400
}
401401

402+
/// The directory the licence-header fixture snapshot is written into. Not
403+
/// tag shaped, for the reason `testWriteSnapshotWritesTheSnapshotAtItsPath`
404+
/// gives, and drawn from the tag alphabet because the writer places files
405+
/// only in directories whose names are.
406+
string constant HEADER_FIXTURE_DIR = "writeSnapshotHeaderNotATag";
407+
408+
/// A written snapshot MUST declare the licence and the copyright holder it
409+
/// was HANDED, each in its own tag.
410+
///
411+
/// They are parameters of this library rather than constants inside it
412+
/// because `rain-deploy` is published and deploy repos in other orgs consume
413+
/// it, so a header chosen here would land in THEIR
414+
/// `src/generated/<tag>/` — append-only, so permanently. That freedom is
415+
/// only worth having if what is handed in is what comes out, and the two are
416+
/// strings of the same type in adjacent positions: a call that swapped them
417+
/// compiles, and writes a file carrying both values, in the wrong tags.
418+
///
419+
/// The alias and released emitters each have a byte-for-byte assertion that
420+
/// covers this. The snapshot writer had none. Everything else in the suite
421+
/// that reads a snapshot header reads the COMMITTED file, which is evidence
422+
/// about a generation that already happened rather than about what the
423+
/// writer emits now — so a swap here would reach a consumer's frozen record
424+
/// with a green suite behind it.
425+
///
426+
/// The expected text is spelled out rather than taken from
427+
/// `LibCodeGen.filePrefix`, so the oracle does not come from the code that
428+
/// wrote the file. `pragma` is the first byte of the header that is neither
429+
/// parameter, so splitting there is the whole of what the two of them
430+
/// produce — an assertion on the header ENTIRE rather than on either value
431+
/// appearing somewhere in it.
432+
///
433+
/// Split across `string.concat` so `reuse lint` does not read the expected
434+
/// text as a licence declaration this test file is making about itself.
435+
///
436+
/// Read before the fixture is removed and asserted after, because forge-std
437+
/// assertions revert: cleaning up afterwards cleans up in every case except
438+
/// a failure, which is the one case that leaves a directory under the real
439+
/// `src/generated/` for every suite that walks it.
440+
function testWriteSnapshotDeclaresTheLicenceItWasHanded() external {
441+
string memory source = vm.readFile(
442+
LibRainDeploySnapshot.writeSnapshot(
443+
vm,
444+
HEADER_FIXTURE_DIR,
445+
FIXTURE_CONTRACT,
446+
GENERATED_SPDX_LICENSE_IDENTIFIER,
447+
GENERATED_COPYRIGHT_TEXT,
448+
type(MockDeployable).creationCode,
449+
new address[](0)
450+
)
451+
);
452+
453+
//forge-lint: disable-next-line(unsafe-cheatcode)
454+
vm.removeDir(LibRainDeploySnapshot.dirForSnapshot(HEADER_FIXTURE_DIR), true);
455+
456+
assertEq(
457+
vm.split(source, "pragma")[0],
458+
string.concat(
459+
"// SPDX-License",
460+
"-Identifier: ",
461+
GENERATED_SPDX_LICENSE_IDENTIFIER,
462+
"\n",
463+
"// SPDX-FileCopyrightText: ",
464+
GENERATED_COPYRIGHT_TEXT,
465+
"\n"
466+
)
467+
);
468+
}
469+
402470
/// The alias lib this repo's `AddressRegistry` snapshot is re-exported
403471
/// through, and the only file the alias emitter writes here.
404472
///

0 commit comments

Comments
 (0)