Artifact 9a11385e8906f91b51d76b2f45e05746a640b4d394150b608426ee7129a8784a:
- File
internal/verify/corpus_timing_test.go
— part of check-in
[9a9bc65f92]
at
2026-10-19 01:50:41
on branch feat/submanifest-reader
— perf(verify): check blob integrity by walking delta trees once
Verify and Rebuild expanded every blob one at a time through a 256 MiB LRU cache. A real repository's delta chains run hundreds of revisions deep, so evicted chains were walked again from their roots: the blob check on the Fossil SCM repository ran for over 45 minutes.
content.ExpandAll walks each delta tree from its root, as fossil's rebuild_step does, expanding every blob once from its parent's content and binding it to its name. It reports for each blob what a caching Expand of that blob alone reports, and expands blobs no sound root reaches (cycles, phantom-grounded or too-deep chains) on their own for that error. checkBlobs and Verify's checkCheckins both use it and sort their issues by rid, so reports are unchanged. (user: [email protected], size: 2927) [annotate] [blame] [check-ins using] [more...]
package verify import ( "io" "os" "path/filepath" "testing" "time" "github.com/danmestas/go-libfossil/internal/repo" _ "github.com/danmestas/go-libfossil/internal/testdriver" ) // TestCorpusCheckBlobs times the blob-integrity sweep Verify and Rebuild open // with, against a real repository. Skipped unless LIBFOSSIL_CORPUS names one. func TestCorpusCheckBlobs(t *testing.T) { r := openCorpusCopy(t) report := &Report{} start := time.Now() if err := checkBlobs(r, report); err != nil { t.Fatalf("checkBlobs: %v", err) } t.Logf("checked %d blobs in %s: %d ok, %d failed", report.BlobsChecked, time.Since(start).Round(time.Millisecond), report.BlobsOK, report.BlobsFailed) if !report.OK() { t.Errorf("issues: %d, first: %+v", len(report.Issues), report.Issues[0]) } } // TestCorpusRebuild times a whole Rebuild of a real repository. Skipped unless // LIBFOSSIL_CORPUS names one. func TestCorpusRebuild(t *testing.T) { r := openCorpusCopy(t) report, err := Rebuild(r) if err != nil { t.Fatalf("Rebuild: %v", err) } t.Logf("rebuilt in %s: %d blobs checked, %d failed", report.Duration.Round(time.Millisecond), report.BlobsChecked, report.BlobsFailed) if !report.OK() { t.Errorf("issues: %d, first: %+v", len(report.Issues), report.Issues[0]) } } // TestCorpusVerify times a whole Verify of a real repository and logs the // issue count; a corpus can carry derived-table drift Verify rightly reports. // Skipped unless LIBFOSSIL_CORPUS names one. func TestCorpusVerify(t *testing.T) { r := openCorpusCopy(t) report, err := Verify(r) if err != nil { t.Fatalf("Verify: %v", err) } t.Logf("verified in %s: %d blobs checked, %d failed, %d issues", report.Duration.Round(time.Millisecond), report.BlobsChecked, report.BlobsFailed, len(report.Issues)) for i, issue := range report.Issues { if i == 5 { break } t.Logf("issue: %+v", issue) } } // openCorpusCopy opens a private copy of the LIBFOSSIL_CORPUS repository, or // skips the test when none is named. func openCorpusCopy(t *testing.T) *repo.Repo { t.Helper() corpus := os.Getenv("LIBFOSSIL_CORPUS") if corpus == "" { t.Skip("set LIBFOSSIL_CORPUS to a .fossil repository to run") } // Work on a copy: opening a repository creates WAL sidecars next to it. // Stream it, so the copy does not count toward the sweep's peak RSS. work := filepath.Join(t.TempDir(), "corpus.fossil") if err := copyFile(work, corpus); err != nil { t.Fatalf("copy corpus: %v", err) } r, err := repo.Open(work) if err != nil { t.Fatalf("open corpus: %v", err) } t.Cleanup(func() { r.Close() }) return r } func copyFile(dst, src string) error { in, err := os.Open(src) if err != nil { return err } defer in.Close() out, err := os.OpenFile(dst, os.O_WRONLY|os.O_CREATE|os.O_EXCL, 0o600) if err != nil { return err } if _, err := io.Copy(out, in); err != nil { out.Close() return err } return out.Close() }