mirror of
https://github.com/kopia/kopia.git
synced 2026-01-24 06:18:02 -05:00
Rename faketime.AutoAdvance parameter to start for clarity Clarify faketime.ClockTimeWithOffset.Advance documentation Refactor `faketime.TimeAdvance`: Add `faketime.NewAutoAdvance` to create auto-advancing `TimeAdvance` clocks. Refactor faketime.NewTimeAdvance to return non-auto-advancing clocks, which can still be explicitly advanced. Removes the now unused `autoDelta` parameter, since it is always 0. Rename function to `sm.setupCachesAndIndexManagers` It matches the current implementation better. Unexport `indexblob.ManagerV1.epochMgr` Rename function for clarity to `advanceEpochMarker` Cleanup logs after cleaning up epoch manager. This is consistent with quick maintenance as well. Make 'def' a test-local variable instead of a package-level variable, it is not used outside this test. Cleanup epoch test newTestEnv() Misc: * Reword comment and fix typo * Fix log message * `log.Debug` for non-formatted output
93 lines
3.7 KiB
Go
93 lines
3.7 KiB
Go
package listcache
|
|
|
|
import (
|
|
"errors"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
"github.com/kopia/kopia/internal/blobtesting"
|
|
"github.com/kopia/kopia/internal/faketime"
|
|
"github.com/kopia/kopia/internal/gather"
|
|
"github.com/kopia/kopia/internal/testlogging"
|
|
"github.com/kopia/kopia/repo/blob"
|
|
)
|
|
|
|
var errFake = errors.New("fake")
|
|
|
|
func TestListCache(t *testing.T) {
|
|
realStorageTime := faketime.NewTimeAdvance(time.Date(2000, 1, 2, 3, 4, 5, 6, time.UTC))
|
|
realStorage := blobtesting.NewMapStorage(blobtesting.DataMap{}, nil, realStorageTime.NowFunc())
|
|
cacheTime := faketime.NewTimeAdvance(time.Date(2020, 1, 2, 3, 4, 5, 6, time.UTC))
|
|
cachest := blobtesting.NewMapStorage(blobtesting.DataMap{}, nil, cacheTime.NowFunc())
|
|
|
|
lc := NewWrapper(realStorage, cachest, []blob.ID{"n", "xe", "xb"}, []byte("hmac-secret"), 1*time.Minute).(*listCacheStorage)
|
|
lc.cacheTimeFunc = cacheTime.NowFunc()
|
|
|
|
ctx := testlogging.Context(t)
|
|
|
|
blobtesting.AssertListResultsIDs(ctx, t, cachest, "")
|
|
blobtesting.AssertListResultsIDs(ctx, t, lc, "n")
|
|
// cached blob gets written
|
|
blobtesting.AssertListResultsIDs(ctx, t, cachest, "", "n")
|
|
blobtesting.AssertListResultsIDs(ctx, t, lc, "n")
|
|
|
|
// modify underlying storage without going through cache layer
|
|
require.NoError(t, realStorage.PutBlob(ctx, "n1", gather.FromSlice([]byte{1, 2, 3}), blob.PutOptions{}))
|
|
|
|
// still getting empty cached results.
|
|
blobtesting.AssertListResultsIDs(ctx, t, lc, "n")
|
|
|
|
// cache expires, real data is read
|
|
cacheTime.Advance(1 * time.Hour)
|
|
blobtesting.AssertListResultsIDs(ctx, t, lc, "n", "n1")
|
|
require.NoError(t, realStorage.PutBlob(ctx, "n2", gather.FromSlice([]byte{1, 2, 3}), blob.PutOptions{}))
|
|
|
|
// n2 still invisible, "n" is cached.
|
|
blobtesting.AssertListResultsIDs(ctx, t, lc, "n", "n1")
|
|
|
|
// writing "n3" through the cache storage invalidates "n".
|
|
require.NoError(t, lc.PutBlob(ctx, "n3", gather.FromSlice([]byte{1, 2, 3}), blob.PutOptions{}))
|
|
blobtesting.AssertListResultsIDs(ctx, t, lc, "n", "n1", "n2", "n3")
|
|
|
|
// deleting "n2" through the cache storage invalidates "n".
|
|
require.NoError(t, lc.DeleteBlob(ctx, "n2"))
|
|
blobtesting.AssertListResultsIDs(ctx, t, lc, "n", "n1", "n3")
|
|
|
|
// add one more blob.
|
|
require.NoError(t, realStorage.PutBlob(ctx, "n4", gather.FromSlice([]byte{1, 2, 3}), blob.PutOptions{}))
|
|
|
|
// replace "n" in cache storage with invalid data.
|
|
require.NoError(t, cachest.PutBlob(ctx, "n", gather.FromSlice([]byte{1, 2, 3}), blob.PutOptions{}))
|
|
|
|
// on next read, "n" will be discarded and "n4" will be immediately visible.
|
|
blobtesting.AssertListResultsIDs(ctx, t, lc, "n", "n1", "n3", "n4")
|
|
|
|
cacheTime.Advance(1 * time.Hour)
|
|
|
|
// add one more blob.
|
|
blobtesting.AssertListResultsIDs(ctx, t, lc, "n", "n1", "n3", "n4")
|
|
require.NoError(t, realStorage.PutBlob(ctx, "n5", gather.FromSlice([]byte{1, 2, 3}), blob.PutOptions{}))
|
|
blobtesting.AssertListResultsIDs(ctx, t, lc, "n", "n1", "n3", "n4")
|
|
cacheTime.Advance(lc.cacheDuration - 1)
|
|
blobtesting.AssertListResultsIDs(ctx, t, lc, "n", "n1", "n3", "n4")
|
|
cacheTime.Advance(1)
|
|
blobtesting.AssertListResultsIDs(ctx, t, lc, "n", "n1", "n3", "n4", "n5")
|
|
|
|
// explicit flush
|
|
require.NoError(t, realStorage.PutBlob(ctx, "n6", gather.FromSlice([]byte{1, 2, 3}), blob.PutOptions{}))
|
|
blobtesting.AssertListResultsIDs(ctx, t, lc, "n", "n1", "n3", "n4", "n5")
|
|
require.NoError(t, lc.FlushCaches(ctx))
|
|
blobtesting.AssertListResultsIDs(ctx, t, lc, "n", "n1", "n3", "n4", "n5", "n6")
|
|
|
|
// non-cached results
|
|
blobtesting.AssertListResultsIDs(ctx, t, lc, "nc")
|
|
require.NoError(t, realStorage.PutBlob(ctx, "nc1", gather.FromSlice([]byte{1, 2, 3}), blob.PutOptions{}))
|
|
blobtesting.AssertListResultsIDs(ctx, t, lc, "nc", "nc1")
|
|
|
|
require.ErrorIs(t, lc.ListBlobs(ctx, "n", func(m blob.Metadata) error {
|
|
return errFake
|
|
}), errFake)
|
|
}
|