Artifact 295936d2cc7af550e82278da8d001a8e15dbb7157a8900f6a46dea54f4c953ae:
- File
internal/hash/hash_test.go
— part of check-in
[f804878bd3]
at
2026-07-22 23:58:46
on branch trunk
— test: route every fossil-binary gate through one REQUIRE_FOSSIL_BIN helper (#125)
* test: route fossil-binary tests through one REQUIRE_FOSSIL_BIN helper
REQUIRE_FOSSIL_BIN=1 turns a missing fossil binary into a test failure instead of an invisible skip, but only internal/manifest honored it. The six other fossil-dependent sites each did their own exec.LookPath + unconditional t.Skip, so on those a run with no fossil was byte-identical to a passing one.
Add testutil.RequireFossilBin, which resolves the binary the same way FossilBinary does (FOSSIL_BIN override, then PATH) and either skips or fails based on REQUIRE_FOSSIL_BIN. Route testutil.NewTestRepo, both internal/delta CLI round-trips, the four internal/merge validation tests, the internal/xfer sanity check, and the ls-branch-tip repro through it, deleting their bespoke lookup+skip logic. CI already sets REQUIRE_FOSSIL_BIN=1 on the unit-test steps, so this makes all seven sites fail loud on absence while local runs without fossil stay opt-in.
* test: route every fossil-binary gate through RequireFossilBin
The first pass left six sites still deciding for themselves whether a missing fossil binary is a skip or a failure. Three of them (internal/sync's startFossilServer and its two integration tests, manifest's two rebuild tests, the root TestPhaseB_Integration, and hash's TestSHA1_FossilValidation) skipped unconditionally, so with REQUIRE_FOSSIL_BIN=1 and no fossil on PATH those packages still reported ok -- the exact silent pass the flag exists to prevent. The other three had hand-rolled copies of the flag check, which is the duplication that let the original drift happen.
All of them now call testutil.RequireFossilBin, and HasFossil is gone: it was a second, skip-only way to ask the same question, and it is what produced the sites that ignored the flag.
Also validate the FOSSIL_BIN override with LookPath, so a stale path reports "fossil not found" instead of surfacing later as a raw fork/exec error.
* test: resolve fossil binary via RequireFossilBin at remaining call sites
* fix: correct stale module path missed by rebase auto-merge
Three imports added by earlier commits in this branch predated the rebase target and had no corresponding line on main to conflict against, so git's auto-merge carried the old module path through verbatim. (user: [email protected], size: 2163) [annotate] [blame] [check-ins using]
package hash import ( "os" "os/exec" "path/filepath" "strings" "testing" "github.com/danmestas/go-libfossil/testutil" ) func TestSHA1(t *testing.T) { tests := []struct { input string want string }{ {"", "da39a3ee5e6b4b0d3255bfef95601890afd80709"}, {"hello", "aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d"}, {"Fossil SCM", "a4304aff1fcb8a78d973db242692175b2e579612"}, } for _, tt := range tests { got := SHA1([]byte(tt.input)) if got != tt.want { t.Errorf("SHA1(%q) = %q, want %q", tt.input, got, tt.want) } } } func TestSHA3(t *testing.T) { tests := []struct { input string want string }{ {"", "a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a"}, {"hello", "3338be694f50c5f338814986cdf0686453a888b84f424d792af4b9202398f392"}, } for _, tt := range tests { got := SHA3([]byte(tt.input)) if got != tt.want { t.Errorf("SHA3(%q) = %q, want %q", tt.input, got, tt.want) } } } func TestSHA1_FossilValidation(t *testing.T) { if testing.Short() { t.Skip("skipping fossil CLI validation in short mode") } input := []byte("test content for hashing") goHash := SHA1(input) tmpFile := filepath.Join(t.TempDir(), "testfile") os.WriteFile(tmpFile, input, 0644) bin := testutil.RequireFossilBin(t) out, err := exec.Command(bin, "sha1sum", tmpFile).Output() if err != nil { t.Fatalf("fossil sha1sum: %v", err) } fossilHash := strings.Fields(string(out))[0] if goHash != fossilHash { t.Fatalf("SHA1 mismatch: go=%q fossil=%q", goHash, fossilHash) } } func TestSHA3Format(t *testing.T) { got := SHA3([]byte("test")) if len(got) != 64 { t.Fatalf("SHA3 length = %d, want 64", len(got)) } for _, c := range got { if !((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f')) { t.Fatalf("SHA3 contains non-lowercase-hex char: %c", c) } } } func BenchmarkSHA1(b *testing.B) { data := make([]byte, 10000) for i := range data { data[i] = byte(i) } b.ResetTimer() for i := 0; i < b.N; i++ { SHA1(data) } } func BenchmarkSHA3(b *testing.B) { data := make([]byte, 10000) for i := range data { data[i] = byte(i) } b.ResetTimer() for i := 0; i < b.N; i++ { SHA3(data) } }