package api
import (
"path/filepath"
"strings"
"testing"
"craftdesign.group/quarry/internal/artifact"
"craftdesign.group/quarry/internal/index"
)
// A render's memo answers each hash exactly as the index does, a hit and
// a miss alike, and remembers both: a body that links thousands of
// hashes asked the index the same questions three times each.
func TestTheRenderMemoAnswersAsTheIndexDoes(t *testing.T) {
ix, err := index.Open(filepath.Join(t.TempDir(), "index.db"))
if err != nil {
t.Fatal(err)
}
t.Cleanup(func() { ix.Close() })
hash := strings.Repeat("ab", 20)
if err := ix.FoldNow([]index.Parsed{{Hash: hash, Art: &artifact.Artifact{Type: artifact.Manifest,
Date: "2026-10-30T10:00:00", User: "dan", Comment: "fix the thing\n\nmore"}}}); err != nil {
t.Fatal(err)
}
plain := resolver{ix: ix, repo: "r"}
memo := resolver{ix: ix, repo: "r", hm: newHashMemo()}
miss := strings.Repeat("cd", 20)
for _, p := range []string{hash, hash[:12], miss} {
for i := 0; i < 2; i++ {
if a, b := plain.ResolveHash(p), memo.ResolveHash(p); a != b {
t.Errorf("FAIL: %.12s links %q through the memo, %q without", p, b, a)
}
if a, b := plain.DescribeHash(p), memo.DescribeHash(p); a != b {
t.Errorf("FAIL: %.12s reads %q through the memo, %q without", p, b, a)
}
}
}
if memo.ResolveHash(hash) == "" || memo.DescribeHash(hash) != "fix the thing" {
t.Errorf("FAIL: the check-in did not resolve: %q %q", memo.ResolveHash(hash), memo.DescribeHash(hash))
}
if _, seen := memo.hm.checkin[miss]; !seen {
t.Error("FAIL: a miss was not remembered")
}
}
// The prefetch answers a body's full hashes in a few queries, the same
// answers the per-hash lookups give, and settles misses before any is
// asked about.
func TestThePrefetchAnswersAsTheLookupsDo(t *testing.T) {
ix, err := index.Open(filepath.Join(t.TempDir(), "index.db"))
if err != nil {
t.Fatal(err)
}
t.Cleanup(func() { ix.Close() })
hash := strings.Repeat("ab", 32)
if err := ix.FoldNow([]index.Parsed{{Hash: hash, Art: &artifact.Artifact{Type: artifact.Manifest,
Date: "2026-10-30T10:00:00", User: "dan", Comment: "sha3 check-in"}}}); err != nil {
t.Fatal(err)
}
miss := strings.Repeat("cd", 20)
plain := resolver{ix: ix, repo: "r"}
memo := resolver{ix: ix, repo: "r", hm: newHashMemo()}
memo.PrefetchHashes([]string{hash, miss, "abab"})
if m, seen := memo.hm.checkin[hash]; !seen || !m.ok {
t.Error("FAIL: the prefetch did not settle the check-in")
}
if m, seen := memo.hm.checkin[miss]; !seen || m.ok {
t.Error("FAIL: the prefetch did not settle the miss")
}
if _, seen := memo.hm.checkin["abab"]; seen {
t.Error("FAIL: a short prefix was settled by exact match")
}
for _, p := range []string{hash, miss, "abab"} {
if a, b := plain.ResolveHash(p), memo.ResolveHash(p); a != b {
t.Errorf("FAIL: %.12s links %q prefetched, %q not", p, b, a)
}
if a, b := plain.DescribeHash(p), memo.DescribeHash(p); a != b {
t.Errorf("FAIL: %.12s reads %q prefetched, %q not", p, b, a)
}
}
}