frostfs-node/pkg/local_object_storage/metabase/get_test.go
Evgenii Stratonikov f58234aa2f [#1559] metabase: Remove public functions
Reduce public interface of this package. Later each result will contain
an additional status, so it makes more sense to use the same functions
and result processing everywhere.

Signed-off-by: Evgenii Stratonikov <evgeniy@nspcc.ru>
2022-07-21 17:56:06 +03:00

214 lines
4.9 KiB
Go

package meta_test
import (
"bytes"
"fmt"
"os"
"testing"
"github.com/nspcc-dev/neofs-node/pkg/core/object"
meta "github.com/nspcc-dev/neofs-node/pkg/local_object_storage/metabase"
apistatus "github.com/nspcc-dev/neofs-sdk-go/client/status"
cidtest "github.com/nspcc-dev/neofs-sdk-go/container/id/test"
objectSDK "github.com/nspcc-dev/neofs-sdk-go/object"
oid "github.com/nspcc-dev/neofs-sdk-go/object/id"
oidtest "github.com/nspcc-dev/neofs-sdk-go/object/id/test"
"github.com/stretchr/testify/require"
)
func TestDB_Get(t *testing.T) {
db := newDB(t)
raw := generateObject(t)
// equal fails on diff of <nil> attributes and <{}> attributes,
/* so we make non empty attribute slice in parent*/
addAttribute(raw, "foo", "bar")
t.Run("object not found", func(t *testing.T) {
_, err := metaGet(db, object.AddressOf(raw), false)
require.Error(t, err)
})
t.Run("put regular object", func(t *testing.T) {
err := putBig(db, raw)
require.NoError(t, err)
newObj, err := metaGet(db, object.AddressOf(raw), false)
require.NoError(t, err)
require.Equal(t, raw.CutPayload(), newObj)
})
t.Run("put tombstone object", func(t *testing.T) {
raw.SetType(objectSDK.TypeTombstone)
raw.SetID(oidtest.ID())
err := putBig(db, raw)
require.NoError(t, err)
newObj, err := metaGet(db, object.AddressOf(raw), false)
require.NoError(t, err)
require.Equal(t, raw.CutPayload(), newObj)
})
t.Run("put storage group object", func(t *testing.T) {
raw.SetType(objectSDK.TypeStorageGroup)
raw.SetID(oidtest.ID())
err := putBig(db, raw)
require.NoError(t, err)
newObj, err := metaGet(db, object.AddressOf(raw), false)
require.NoError(t, err)
require.Equal(t, raw.CutPayload(), newObj)
})
t.Run("put lock object", func(t *testing.T) {
raw.SetType(objectSDK.TypeLock)
raw.SetID(oidtest.ID())
err := putBig(db, raw)
require.NoError(t, err)
newObj, err := metaGet(db, object.AddressOf(raw), false)
require.NoError(t, err)
require.Equal(t, raw.CutPayload(), newObj)
})
t.Run("put virtual object", func(t *testing.T) {
cnr := cidtest.ID()
splitID := objectSDK.NewSplitID()
parent := generateObjectWithCID(t, cnr)
addAttribute(parent, "foo", "bar")
child := generateObjectWithCID(t, cnr)
child.SetParent(parent)
idParent, _ := parent.ID()
child.SetParentID(idParent)
child.SetSplitID(splitID)
err := putBig(db, child)
require.NoError(t, err)
t.Run("raw is true", func(t *testing.T) {
_, err = metaGet(db, object.AddressOf(parent), true)
require.Error(t, err)
siErr, ok := err.(*objectSDK.SplitInfoError)
require.True(t, ok)
require.Equal(t, splitID, siErr.SplitInfo().SplitID())
id1, _ := child.ID()
id2, _ := siErr.SplitInfo().LastPart()
require.Equal(t, id1, id2)
_, ok = siErr.SplitInfo().Link()
require.False(t, ok)
})
newParent, err := metaGet(db, object.AddressOf(parent), false)
require.NoError(t, err)
require.True(t, binaryEqual(parent.CutPayload(), newParent))
newChild, err := metaGet(db, object.AddressOf(child), true)
require.NoError(t, err)
require.True(t, binaryEqual(child.CutPayload(), newChild))
})
t.Run("get removed object", func(t *testing.T) {
obj := oidtest.Address()
ts := oidtest.Address()
require.NoError(t, metaInhume(db, obj, ts))
_, err := metaGet(db, obj, false)
require.ErrorAs(t, err, new(apistatus.ObjectAlreadyRemoved))
obj = oidtest.Address()
var prm meta.InhumePrm
prm.WithAddresses(obj)
_, err = db.Inhume(prm)
require.NoError(t, err)
_, err = metaGet(db, obj, false)
require.ErrorAs(t, err, new(apistatus.ObjectNotFound))
})
}
// binary equal is used when object contains empty lists in the structure and
// requre.Equal fails on comparing <nil> and []{} lists.
func binaryEqual(a, b *objectSDK.Object) bool {
binaryA, err := a.Marshal()
if err != nil {
return false
}
binaryB, err := b.Marshal()
if err != nil {
return false
}
return bytes.Equal(binaryA, binaryB)
}
func BenchmarkGet(b *testing.B) {
numOfObjects := [...]int{
1,
10,
100,
}
for _, num := range numOfObjects {
b.Run(fmt.Sprintf("%d objects", num), func(b *testing.B) {
benchmarkGet(b, num)
})
}
}
var obj *objectSDK.Object
func benchmarkGet(b *testing.B, numOfObj int) {
db := newDB(b)
addrs := make([]oid.Address, 0, numOfObj)
for i := 0; i < numOfObj; i++ {
raw := generateObject(b)
addrs = append(addrs, object.AddressOf(raw))
err := putBig(db, raw)
require.NoError(b, err)
}
b.Cleanup(func() {
_ = db.Close()
_ = os.RemoveAll(b.Name())
})
b.ReportAllocs()
b.ResetTimer()
var getPrm meta.GetPrm
getPrm.WithAddress(addrs[len(addrs)/2])
for i := 0; i < b.N; i++ {
for _, addr := range addrs {
getPrm.WithAddress(addr)
res, err := db.Get(getPrm)
require.NoError(b, err)
obj = res.Header()
}
}
}
func metaGet(db *meta.DB, addr oid.Address, raw bool) (*objectSDK.Object, error) {
var prm meta.GetPrm
prm.WithAddress(addr)
prm.WithRaw(raw)
res, err := db.Get(prm)
return res.Header(), err
}