Test that a hashed twin with other bytes is never listed
Fingerprinted lists a hashed asset only when its bytes equal its plain twin's, so a corrupted copy under the right name is never told to browsers as immutable. No test held that: the test's wrong twin had a name whose hex was not the plain file's hash, so the name lookup already left it out, and with the byte comparison deleted the test still passed. The new fixture is a twin under the plain file's true hashed name holding other bytes. It is not listed. This is a test of code that already does the right thing, so it is labelled already passing. The mutation that turns it red: in Fingerprinted, drop the byte comparison and keep only the name lookup. With that mutation the new test fails, listing the corrupted twin, and the old test passes.
Human
Prompt
Minor: the corrupted hashed-twin case has no regression test (internal/gallery/hashed_test.go:24). Add a twin named with the plain file's real hash but holding different bytes, and assert it's excluded. Show it red with the byte-equality check removed.
From this commit's own message. The prompt ledger has no entries for it — which is what a squashed, rebased or amended commit looks like, and what every commit looks like in a repo without a ledger.
Summary
A twin under the plain file's real hashed name but with other bytes is excluded by Fingerprinted; red with the byte check removed.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 file changed,
+6
−0
internal/gallery/hashed_test.go+6 −0
Intent
diff --git a/internal/gallery/hashed_test.go b/internal/gallery/hashed_test.go| index bcf3930..43e287a 100644 |
| --- a/internal/gallery/hashed_test.go |
| +++ b/internal/gallery/hashed_test.go |
| @@ -11,8 +11,12 @@ import ( |
| // change under the same name, and neither is a name that merely looks |
| // hashed: one whose hex is not its own bytes' hash, or one with no |
| // plain twin, could be replaced by other bytes under the same name. |
| +// Nor is a twin under the plain file's true hashed name that holds |
| +// other bytes, a corrupted copy: the name is right, so only comparing |
| +// the bytes keeps a browser from holding the wrong ones for a year. |
| func TestFingerprintedNamesTheHashedTwinsOnly(t *testing.T) { |
| css, js, pic := []byte("body{}\n"), []byte("0\n"), []byte("GIF89a") |
| + plain, corrupted := []byte("main{}\n"), []byte("main{color:red}\n") |
| tree := map[string][]byte{ |
| "assets/css/fiesta.css": css, |
| "assets/css/" + hashedName("fiesta.css", css): css, |
| @@ -23,6 +27,8 @@ func TestFingerprintedNamesTheHashedTwinsOnly(t *testing.T) { |
| "assets/lone.0123456789abcdef.css": css, |
| "assets/wrong.css": css, |
| "assets/wrong.0123456789abcdef.css": css, |
| + "assets/torn.css": plain, |
| + "assets/" + hashedName("torn.css", plain): corrupted, |
| "day/en/" + hashedName("page.html", js): js, |
| "day/en/page.html": js, |
| } |