defmodule GitGud.Workflows.ActionsCacheTest do
@moduledoc """
Covers the GitHub-spec lookup ordering implemented in
`ActionsCache.lookup/5` — primary exact, fallbacks prefix, current
ref then default ref. Storage interaction is exercised once via the
Disk backend; the heavy work is in lookup precedence.
"""
use GitGud.DataCase, async: false
alias GitGud.Workflows.ActionsCache
alias GitGud.Workflows.CacheEntry
import GitGud.ForgeFixtures
setup do
{_user, repo} = repository_fixture()
{:ok, repo: repo}
end
defp seed(repo, key, version, ref, body \\ "x") do
{:ok, entry} = ActionsCache.reserve(repo, key, version, ref)
:ok = ActionsCache.append(entry, body)
{:ok, entry} = ActionsCache.finalize(entry, byte_size(body))
entry
end
describe "lookup/5" do
test "exact primary match on the current ref wins", %{repo: repo} do
hit_entry = seed(repo, "deps-v1", "vhash", "refs/heads/feature")
_other = seed(repo, "deps-v1", "vhash", "refs/heads/main", "old")
hit =
ActionsCache.lookup(
repo.id,
"vhash",
["deps-v1"],
"refs/heads/feature",
"refs/heads/main"
)
assert hit.entry.id == hit_entry.id
assert hit.matched_key == "deps-v1"
end
test "falls back to default ref when current ref has no match", %{repo: repo} do
hit_entry = seed(repo, "deps-v1", "vhash", "refs/heads/main")
hit =
ActionsCache.lookup(
repo.id,
"vhash",
["deps-v1"],
"refs/heads/feature",
"refs/heads/main"
)
assert hit.entry.id == hit_entry.id
end
test "primary miss + fallback prefix match", %{repo: repo} do
hit_entry = seed(repo, "deps-v1-abc", "vhash", "refs/heads/feature")
hit =
ActionsCache.lookup(
repo.id,
"vhash",
["never-existed", "deps-v1-"],
"refs/heads/feature",
"refs/heads/main"
)
assert hit.entry.id == hit_entry.id
# `matched_key` carries the row's key, not the prefix that matched.
assert hit.matched_key == "deps-v1-abc"
end
test "version mismatch is a miss even with key match", %{repo: repo} do
_ = seed(repo, "deps-v1", "vhash-A", "refs/heads/feature")
assert nil ==
ActionsCache.lookup(
repo.id,
"vhash-B",
["deps-v1"],
"refs/heads/feature",
"refs/heads/main"
)
end
test "pending (unfinalized) row is invisible to lookup", %{repo: repo} do
{:ok, _} = ActionsCache.reserve(repo, "deps-v1", "vhash", "refs/heads/feature")
assert nil ==
ActionsCache.lookup(
repo.id,
"vhash",
["deps-v1"],
"refs/heads/feature",
"refs/heads/main"
)
end
test "empty keys list returns nil", %{repo: repo} do
assert nil == ActionsCache.lookup(repo.id, "v", [], "refs/heads/x", "refs/heads/main")
end
end
describe "reserve/4" do
test "re-reserving the same triple replaces the prior pending row", %{repo: repo} do
{:ok, a} = ActionsCache.reserve(repo, "k", "v", "refs/heads/main")
{:ok, b} = ActionsCache.reserve(repo, "k", "v", "refs/heads/main")
# Same row, refreshed.
assert a.id == b.id
[row] =
GitGud.Repo.all(
from c in CacheEntry,
where: c.repository_id == ^repo.id and c.key == "k"
)
assert row.id == a.id
refute CacheEntry.finalized?(row)
end
end
describe "append + finalize" do
test "round-trips bytes via Storage", %{repo: repo} do
{:ok, entry} = ActionsCache.reserve(repo, "k", "v", "refs/heads/main")
:ok = ActionsCache.append(entry, "hello ")
:ok = ActionsCache.append(entry, "world")
{:ok, finalized} = ActionsCache.finalize(entry, 11)
assert finalized.size == 11
assert CacheEntry.finalized?(finalized)
{:ok, body} = GitGud.Storage.get(ActionsCache.bucket(), finalized.storage_key)
assert body == "hello world"
end
end
end
4.1 KiB · text
5af55d9