mirror of
https://github.com/restic/restic.git
synced 2024-12-23 08:16:36 +00:00
155 lines
3.7 KiB
Go
155 lines
3.7 KiB
Go
|
package index
|
||
|
|
||
|
import (
|
||
|
"context"
|
||
|
"testing"
|
||
|
|
||
|
"github.com/restic/restic/internal/crypto"
|
||
|
"github.com/restic/restic/internal/restic"
|
||
|
"github.com/restic/restic/internal/test"
|
||
|
)
|
||
|
|
||
|
type noopSaver struct{}
|
||
|
|
||
|
func (n *noopSaver) Connections() uint {
|
||
|
return 2
|
||
|
}
|
||
|
func (n *noopSaver) SaveUnpacked(ctx context.Context, t restic.FileType, buf []byte) (restic.ID, error) {
|
||
|
return restic.Hash(buf), nil
|
||
|
}
|
||
|
|
||
|
func makeFakePackedBlob() (restic.BlobHandle, restic.PackedBlob) {
|
||
|
bh := restic.NewRandomBlobHandle()
|
||
|
blob := restic.PackedBlob{
|
||
|
PackID: restic.NewRandomID(),
|
||
|
Blob: restic.Blob{
|
||
|
BlobHandle: bh,
|
||
|
Length: uint(crypto.CiphertextLength(10)),
|
||
|
Offset: 0,
|
||
|
},
|
||
|
}
|
||
|
return bh, blob
|
||
|
}
|
||
|
|
||
|
func TestAssociatedSet(t *testing.T) {
|
||
|
bh, blob := makeFakePackedBlob()
|
||
|
|
||
|
mi := NewMasterIndex()
|
||
|
mi.StorePack(blob.PackID, []restic.Blob{blob.Blob})
|
||
|
test.OK(t, mi.SaveIndex(context.TODO(), &noopSaver{}))
|
||
|
|
||
|
bs := NewAssociatedSet[uint8](mi)
|
||
|
test.Equals(t, bs.Len(), 0)
|
||
|
test.Equals(t, bs.List(), restic.BlobHandles{})
|
||
|
|
||
|
// check non existent
|
||
|
test.Equals(t, bs.Has(bh), false)
|
||
|
_, ok := bs.Get(bh)
|
||
|
test.Equals(t, false, ok)
|
||
|
|
||
|
// test insert
|
||
|
bs.Insert(bh)
|
||
|
test.Equals(t, bs.Has(bh), true)
|
||
|
test.Equals(t, bs.Len(), 1)
|
||
|
test.Equals(t, bs.List(), restic.BlobHandles{bh})
|
||
|
test.Equals(t, 0, len(bs.overflow))
|
||
|
|
||
|
// test set
|
||
|
bs.Set(bh, 42)
|
||
|
test.Equals(t, bs.Has(bh), true)
|
||
|
test.Equals(t, bs.Len(), 1)
|
||
|
val, ok := bs.Get(bh)
|
||
|
test.Equals(t, true, ok)
|
||
|
test.Equals(t, uint8(42), val)
|
||
|
|
||
|
s := bs.String()
|
||
|
test.Assert(t, len(s) > 10, "invalid string: %v", s)
|
||
|
|
||
|
// test remove
|
||
|
bs.Delete(bh)
|
||
|
test.Equals(t, bs.Len(), 0)
|
||
|
test.Equals(t, bs.Has(bh), false)
|
||
|
test.Equals(t, bs.List(), restic.BlobHandles{})
|
||
|
|
||
|
test.Equals(t, "{}", bs.String())
|
||
|
|
||
|
// test set
|
||
|
bs.Set(bh, 43)
|
||
|
test.Equals(t, bs.Has(bh), true)
|
||
|
test.Equals(t, bs.Len(), 1)
|
||
|
val, ok = bs.Get(bh)
|
||
|
test.Equals(t, true, ok)
|
||
|
test.Equals(t, uint8(43), val)
|
||
|
test.Equals(t, 0, len(bs.overflow))
|
||
|
// test update
|
||
|
bs.Set(bh, 44)
|
||
|
val, ok = bs.Get(bh)
|
||
|
test.Equals(t, true, ok)
|
||
|
test.Equals(t, uint8(44), val)
|
||
|
test.Equals(t, 0, len(bs.overflow))
|
||
|
|
||
|
// test overflow blob
|
||
|
of := restic.NewRandomBlobHandle()
|
||
|
test.Equals(t, false, bs.Has(of))
|
||
|
// set
|
||
|
bs.Set(of, 7)
|
||
|
test.Equals(t, 1, len(bs.overflow))
|
||
|
test.Equals(t, bs.Len(), 2)
|
||
|
// get
|
||
|
val, ok = bs.Get(of)
|
||
|
test.Equals(t, true, ok)
|
||
|
test.Equals(t, uint8(7), val)
|
||
|
test.Equals(t, bs.List(), restic.BlobHandles{of, bh})
|
||
|
// update
|
||
|
bs.Set(of, 8)
|
||
|
val, ok = bs.Get(of)
|
||
|
test.Equals(t, true, ok)
|
||
|
test.Equals(t, uint8(8), val)
|
||
|
test.Equals(t, 1, len(bs.overflow))
|
||
|
// delete
|
||
|
bs.Delete(of)
|
||
|
test.Equals(t, bs.Len(), 1)
|
||
|
test.Equals(t, bs.Has(of), false)
|
||
|
test.Equals(t, bs.List(), restic.BlobHandles{bh})
|
||
|
test.Equals(t, 0, len(bs.overflow))
|
||
|
}
|
||
|
|
||
|
func TestAssociatedSetWithExtendedIndex(t *testing.T) {
|
||
|
_, blob := makeFakePackedBlob()
|
||
|
|
||
|
mi := NewMasterIndex()
|
||
|
mi.StorePack(blob.PackID, []restic.Blob{blob.Blob})
|
||
|
test.OK(t, mi.SaveIndex(context.TODO(), &noopSaver{}))
|
||
|
|
||
|
bs := NewAssociatedSet[uint8](mi)
|
||
|
|
||
|
// add new blobs to index after building the set
|
||
|
of, blob2 := makeFakePackedBlob()
|
||
|
mi.StorePack(blob2.PackID, []restic.Blob{blob2.Blob})
|
||
|
test.OK(t, mi.SaveIndex(context.TODO(), &noopSaver{}))
|
||
|
|
||
|
// non-existant
|
||
|
test.Equals(t, false, bs.Has(of))
|
||
|
// set
|
||
|
bs.Set(of, 5)
|
||
|
test.Equals(t, 1, len(bs.overflow))
|
||
|
test.Equals(t, bs.Len(), 1)
|
||
|
// get
|
||
|
val, ok := bs.Get(of)
|
||
|
test.Equals(t, true, ok)
|
||
|
test.Equals(t, uint8(5), val)
|
||
|
test.Equals(t, bs.List(), restic.BlobHandles{of})
|
||
|
// update
|
||
|
bs.Set(of, 8)
|
||
|
val, ok = bs.Get(of)
|
||
|
test.Equals(t, true, ok)
|
||
|
test.Equals(t, uint8(8), val)
|
||
|
test.Equals(t, 1, len(bs.overflow))
|
||
|
// delete
|
||
|
bs.Delete(of)
|
||
|
test.Equals(t, bs.Len(), 0)
|
||
|
test.Equals(t, bs.Has(of), false)
|
||
|
test.Equals(t, bs.List(), restic.BlobHandles{})
|
||
|
test.Equals(t, 0, len(bs.overflow))
|
||
|
}
|