Files
kopia/repo/content/committed_content_index_cache_test.go
Jarek Kowalski b55d5b474c refactor(repository): refactored internal index read API to reduce memory allocations (#3754)
* refactor(repository): refactored internal index read API to reduce memory allocations

* fixed stress test flake, improved debuggability

* fixed spurious checklocks failures

* post-merge fixes

* pr feedback
2024-04-12 22:59:11 -07:00

140 lines
3.8 KiB
Go

package content
import (
"bytes"
"testing"
"time"
"github.com/stretchr/testify/require"
"github.com/kopia/kopia/internal/faketime"
"github.com/kopia/kopia/internal/gather"
"github.com/kopia/kopia/internal/testlogging"
"github.com/kopia/kopia/internal/testutil"
"github.com/kopia/kopia/repo/blob"
"github.com/kopia/kopia/repo/content/index"
)
func TestCommittedContentIndexCache_Disk(t *testing.T) {
t.Parallel()
ta := faketime.NewClockTimeWithOffset(0)
testCache(t, &diskCommittedContentIndexCache{testutil.TempDirectory(t), ta.NowFunc(), func() int { return 3 }, testlogging.Printf(t.Logf, ""), DefaultIndexCacheSweepAge}, ta)
}
func TestCommittedContentIndexCache_Memory(t *testing.T) {
t.Parallel()
testCache(t, &memoryCommittedContentIndexCache{
contents: map[blob.ID]index.Index{},
v1PerContentOverhead: func() int { return 3 },
}, nil)
}
//nolint:thelper
func testCache(t *testing.T, cache committedContentIndexCache, fakeTime *faketime.ClockTimeWithOffset) {
ctx := testlogging.Context(t)
has, err := cache.hasIndexBlobID(ctx, "ndx1")
require.NoError(t, err)
if has {
t.Fatal("hasIndexBlobID invalid response, expected false")
}
if _, err = cache.openIndex(ctx, "ndx1"); err == nil {
t.Fatal("openIndex unexpectedly succeeded")
}
require.NoError(t, cache.addContentToCache(ctx, "ndx1", mustBuildIndex(t, index.Builder{
mustParseID(t, "c1"): Info{PackBlobID: "p1234", ContentID: mustParseID(t, "c1")},
mustParseID(t, "c2"): Info{PackBlobID: "p1234", ContentID: mustParseID(t, "c2")},
})))
has, err = cache.hasIndexBlobID(ctx, "ndx1")
require.NoError(t, err)
if !has {
t.Fatal("hasIndexBlobID invalid response, expected true")
}
require.NoError(t, cache.addContentToCache(ctx, "ndx2", mustBuildIndex(t, index.Builder{
mustParseID(t, "c3"): Info{PackBlobID: "p2345", ContentID: mustParseID(t, "c3")},
mustParseID(t, "c4"): Info{PackBlobID: "p2345", ContentID: mustParseID(t, "c4")},
})))
require.NoError(t, cache.addContentToCache(ctx, "ndx2", mustBuildIndex(t, index.Builder{
mustParseID(t, "c3"): Info{PackBlobID: "p2345", ContentID: mustParseID(t, "c3")},
mustParseID(t, "c4"): Info{PackBlobID: "p2345", ContentID: mustParseID(t, "c4")},
})))
ndx1, err := cache.openIndex(ctx, "ndx1")
require.NoError(t, err)
ndx2, err := cache.openIndex(ctx, "ndx2")
require.NoError(t, err)
var i Info
ok, err := ndx1.GetInfo(mustParseID(t, "c1"), &i)
require.True(t, ok)
require.NoError(t, err)
if got, want := i.PackBlobID, blob.ID("p1234"); got != want {
t.Fatalf("unexpected pack blob ID: %v, want %v", got, want)
}
require.NoError(t, ndx1.Close())
ok, err = ndx2.GetInfo(mustParseID(t, "c3"), &i)
require.True(t, ok)
require.NoError(t, err)
if got, want := i.PackBlobID, blob.ID("p2345"); got != want {
t.Fatalf("unexpected pack blob ID: %v, want %v", got, want)
}
// expire leaving only ndx2, this will actually not do anything for disk cache
// because it relies on passage of time for safety, we'll re-do it in a sec.
require.NoError(t, cache.expireUnused(ctx, []blob.ID{"ndx2"}))
if fakeTime != nil {
fakeTime.Advance(2 * time.Hour)
}
// expire leaving only ndx2
require.NoError(t, cache.expireUnused(ctx, []blob.ID{"ndx2"}))
has, err = cache.hasIndexBlobID(ctx, "ndx1")
require.NoError(t, err)
if has {
t.Fatal("hasIndexBlobID invalid response, expected false")
}
if _, err = cache.openIndex(ctx, "ndx1"); err == nil {
t.Fatal("openIndex unexpectedly succeeded")
}
}
func mustBuildIndex(t *testing.T, b index.Builder) gather.Bytes {
t.Helper()
var buf bytes.Buffer
if err := b.Build(&buf, index.Version2); err != nil {
t.Fatal(err)
}
return gather.FromSlice(buf.Bytes())
}
func mustParseID(t *testing.T, s string) ID {
t.Helper()
id, err := index.ParseID(s)
require.NoError(t, err)
return id
}