123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204 |
- package blob_test
- import (
- "context"
- "sync"
- "testing"
- "time"
- "github.com/pkg/errors"
- "github.com/stretchr/testify/require"
- "github.com/kopia/kopia/internal/blobtesting"
- "github.com/kopia/kopia/internal/gather"
- "github.com/kopia/kopia/repo/blob"
- )
- func TestListAllBlobs(t *testing.T) {
- data := blobtesting.DataMap{}
- st := blobtesting.NewMapStorage(data, nil, nil)
- ctx := context.Background()
- st.PutBlob(ctx, "foo", gather.FromSlice([]byte{1, 2, 3}), blob.PutOptions{})
- st.PutBlob(ctx, "boo", gather.FromSlice([]byte{2, 3, 4}), blob.PutOptions{})
- st.PutBlob(ctx, "bar", gather.FromSlice([]byte{3, 4, 5}), blob.PutOptions{})
- result1, err := blob.ListAllBlobs(ctx, st, "")
- require.NoError(t, err)
- require.ElementsMatch(t, []blob.ID{"foo", "boo", "bar"}, blob.IDsFromMetadata(result1))
- result2, err := blob.ListAllBlobs(ctx, st, "b")
- require.NoError(t, err)
- require.ElementsMatch(t, []blob.ID{"boo", "bar"}, blob.IDsFromMetadata(result2))
- result3, err := blob.ListAllBlobs(ctx, st, "c")
- require.NoError(t, err)
- require.ElementsMatch(t, []blob.ID{}, blob.IDsFromMetadata(result3))
- }
- func TestIterateAllPrefixesInParallel(t *testing.T) {
- data := blobtesting.DataMap{}
- st := blobtesting.NewMapStorage(data, nil, nil)
- ctx := context.Background()
- st.PutBlob(ctx, "foo", gather.FromSlice([]byte{1, 2, 3}), blob.PutOptions{})
- st.PutBlob(ctx, "boo", gather.FromSlice([]byte{2, 3, 4}), blob.PutOptions{})
- st.PutBlob(ctx, "bar", gather.FromSlice([]byte{3, 4, 5}), blob.PutOptions{})
- var (
- mu sync.Mutex
- got []blob.ID
- )
- require.NoError(t, blob.IterateAllPrefixesInParallel(ctx, 10, st, []blob.ID{
- "b",
- "c",
- }, func(m blob.Metadata) error {
- mu.Lock()
- defer mu.Unlock()
- got = append(got, m.BlobID)
- return nil
- }))
- require.ElementsMatch(t, []blob.ID{"boo", "bar"}, got)
- got = nil
- require.NoError(t, blob.IterateAllPrefixesInParallel(ctx, 0, st, []blob.ID{
- "f",
- }, func(m blob.Metadata) error {
- mu.Lock()
- defer mu.Unlock()
- got = append(got, m.BlobID)
- return nil
- }))
- require.ElementsMatch(t, []blob.ID{"foo"}, got)
- got = nil
- require.NoError(t, blob.IterateAllPrefixesInParallel(ctx, 0, st, []blob.ID{
- "f",
- "b",
- }, func(m blob.Metadata) error {
- mu.Lock()
- defer mu.Unlock()
- got = append(got, m.BlobID)
- return nil
- }))
- require.ElementsMatch(t, []blob.ID{"foo", "bar", "boo"}, got)
- errDummy := errors.New("dummy")
- require.ErrorIs(t, errDummy, blob.IterateAllPrefixesInParallel(ctx, 10, st, []blob.ID{
- "b",
- "c",
- }, func(m blob.Metadata) error {
- return errDummy
- }))
- }
- func TestEnsureLengthExactly(t *testing.T) {
- require.NoError(t, blob.EnsureLengthExactly(3, 3))
- require.NoError(t, blob.EnsureLengthExactly(3, -1))
- require.Error(t, blob.EnsureLengthExactly(3, 4))
- require.Error(t, blob.EnsureLengthExactly(3, 2))
- }
- func TestIDsFromMetadata(t *testing.T) {
- require.Equal(t,
- []blob.ID{"foo", "bar", "baz"},
- blob.IDsFromMetadata([]blob.Metadata{
- {BlobID: "foo", Length: 11},
- {BlobID: "bar", Length: 22},
- {BlobID: "baz", Length: 55},
- }))
- }
- func TestMaxTimestamp(t *testing.T) {
- t0 := time.Date(2020, 1, 2, 3, 4, 5, 6, time.UTC)
- t1 := t0.Add(1 * time.Hour)
- t2 := t0.Add(-1 * time.Hour)
- require.Equal(t,
- t1,
- blob.MaxTimestamp([]blob.Metadata{
- {BlobID: "foo", Timestamp: t0},
- {BlobID: "bar", Timestamp: t1},
- {BlobID: "baz", Timestamp: t2},
- }))
- require.Equal(t, time.Time{}, blob.MaxTimestamp([]blob.Metadata{}))
- }
- func TestMinTimestamp(t *testing.T) {
- t0 := time.Date(2020, 1, 2, 3, 4, 5, 6, time.UTC)
- t1 := t0.Add(1 * time.Hour)
- t2 := t0.Add(-1 * time.Hour)
- require.Equal(t,
- t2,
- blob.MinTimestamp([]blob.Metadata{
- {BlobID: "foo", Timestamp: t0},
- {BlobID: "bar", Timestamp: t1},
- {BlobID: "baz", Timestamp: t2},
- }))
- require.Equal(t, time.Time{}, blob.MinTimestamp([]blob.Metadata{}))
- }
- func TestTotalLength(t *testing.T) {
- require.Equal(t,
- int64(357),
- blob.TotalLength([]blob.Metadata{
- {BlobID: "foo", Length: 123},
- {BlobID: "bar", Length: 234},
- }))
- }
- func TestDeleteMultiple(t *testing.T) {
- data := blobtesting.DataMap{
- "foo": []byte{1, 2, 3},
- "bar": []byte{1, 2, 4},
- "baz": []byte{1, 2, 5},
- "qux": []byte{1, 2, 6},
- }
- st := blobtesting.NewMapStorage(data, nil, nil)
- require.NoError(t, blob.DeleteMultiple(context.Background(), st, []blob.ID{"bar", "qux"}, 4))
- require.Equal(t, blobtesting.DataMap{
- "foo": []byte{1, 2, 3},
- "baz": []byte{1, 2, 5},
- }, data)
- }
- func TestMetadataJSONString(t *testing.T) {
- bm := blob.Metadata{
- BlobID: "foo",
- Length: 12345,
- Timestamp: time.Date(2000, 1, 2, 3, 4, 5, 6, time.UTC),
- }
- require.JSONEq(t, `{"id":"foo","length":12345,"timestamp":"2000-01-02T03:04:05.000000006Z"}`, bm.String())
- }
- func TestPutBlobAndGetMetadata(t *testing.T) {
- data := blobtesting.DataMap{}
- fixedTime := time.Date(2000, 1, 2, 3, 4, 5, 6, time.UTC)
- st := blobtesting.NewMapStorage(data, nil, func() time.Time {
- return fixedTime
- })
- bm, err := blob.PutBlobAndGetMetadata(context.Background(), st, "foo", gather.FromSlice([]byte{1, 2, 3}), blob.PutOptions{})
- require.NoError(t, err)
- require.Equal(t, fixedTime, bm.Timestamp)
- }
|