Skip to content

Commit

Permalink
WIP: unit tests
Browse files Browse the repository at this point in the history
Signed-off-by: Leonard Lyubich <[email protected]>
  • Loading branch information
cthulhu-rider committed Jan 16, 2025
1 parent 3bf58af commit f16c1c1
Showing 1 changed file with 114 additions and 2 deletions.
116 changes: 114 additions & 2 deletions pkg/local_object_storage/metabase/metadata_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"encoding/base64"
"math/rand"
"slices"
"strconv"
"testing"

"github.com/nspcc-dev/neofs-sdk-go/checksum"
Expand All @@ -15,11 +16,18 @@ import (
oid "github.com/nspcc-dev/neofs-sdk-go/object/id"
oidtest "github.com/nspcc-dev/neofs-sdk-go/object/id/test"
"github.com/nspcc-dev/neofs-sdk-go/user"
usertest "github.com/nspcc-dev/neofs-sdk-go/user/test"
"github.com/nspcc-dev/neofs-sdk-go/version"
"github.com/stretchr/testify/require"
"go.etcd.io/bbolt"
)

func sortObjectIDs(ids []oid.ID) []oid.ID {
s := slices.Clone(ids)
slices.SortFunc(s, func(a, b oid.ID) int { return bytes.Compare(a[:], b[:]) })
return s
}

func assertAttrPrefixed[T string | []byte](t testing.TB, mb *bbolt.Bucket, id oid.ID, prefix byte, attr string, val T) {
k := []byte{prefix}
k = append(k, attr...)
Expand Down Expand Up @@ -191,8 +199,7 @@ func TestDB_SearchObjects(t *testing.T) {
require.NoError(t, err, i)
}

idsSorted := slices.Clone(ids)
slices.SortFunc(idsSorted, func(a, b oid.ID) int { return bytes.Compare(a[:], b[:]) })
idsSorted := sortObjectIDs(ids)

t.Run("all at once", func(t *testing.T) {
for _, tc := range []struct {
Expand Down Expand Up @@ -259,4 +266,109 @@ func TestDB_SearchObjects(t *testing.T) {
require.EqualError(t, err, "view BoltDB: unexpected object key len 31, expected 33")
})
})
t.Run("filters", func(t *testing.T) {
cnr := cidtest.ID()
owner1, owner2 := usertest.ID(), usertest.ID()
const n = 4
var objs [n]object.Object
ids := make([]oid.ID, len(objs))
for i := range objs {
objs[i].SetContainerID(cnr)
objs[i].SetPayloadChecksum(checksumtest.Checksum()) // required to Put
if i%2 == 0 {
objs[i].SetOwnerID(&owner1)
} else {
objs[i].SetOwnerID(&owner2)
}

id := oidtest.ID()
objs[i].SetID(id)

si := strconv.Itoa(i)
objs[i].SetAttributes(
*object.NewAttribute("attr_"+si, "val_"+si),
*object.NewAttribute("attr_common", "val_common"),
)

require.NoError(t, db.Put(&objs[i], nil, nil))
}

ids = sortObjectIDs(ids)

check := func(k string, m object.SearchMatchType, v string, matchInds []uint) {
var fs object.SearchFilters
fs.AddFilter("attr_common", "val_common", object.MatchStringEqual)
fs.AddFilter(k, v, m)

res, cursor, err := db.Search(cnr, fs, []string{"attr_common"}, "", n)
require.NoError(t, err)
require.Empty(t, cursor)
require.Len(t, res, len(matchInds))
for i, ind := range matchInds {
require.Equal(t, ids[ind], res[i].ID)
require.Len(t, res[i].Attributes, 1)
require.Equal(t, "val_common", res[i].Attributes[0])
}
}

t.Run("container", func(t *testing.T) {
// Since container ID is a selection parameter itself, only EQ and PREFIX with
// CID prefix match. For other prefixes, result is always empty, and it can be
// obtained without touching the BoltDB.
check := func(m object.SearchMatchType, v string, match bool) {
var inds []uint
if match {
inds = []uint{0, 1, 2, 3}
}
check(object.FilterContainerID, m, v, inds)
}

cnrStr := cnr.EncodeToString()
otherCnrStr := cidtest.OtherID(cnr).EncodeToString()
check(object.MatchStringEqual, cnrStr, true)
check(object.MatchStringEqual, otherCnrStr, false)
check(object.MatchStringNotEqual, cnrStr, false)
check(object.MatchStringNotEqual, otherCnrStr, true)
for _, m := range []object.SearchMatchType{
object.MatchNotPresent, object.MatchNumGT, object.MatchNumGE, object.MatchNumLT, object.MatchNumLE,
} {
check(m, cnrStr, false)
check(m, otherCnrStr, false)
}
for i := range len(cnrStr) {
check(object.MatchCommonPrefix, cnrStr[:i], true)
if cnrStr[:i] != otherCnrStr[:i] {
check(object.MatchCommonPrefix, otherCnrStr[:i], false)
}
}
// TODO: also check that BoltDB is untouched when on mismatch
})
t.Run("owner", func(t *testing.T) {
check := func(m object.SearchMatchType, v string, matchInds []uint) {
check(object.FilterOwnerID, m, v, matchInds)
}
owner1Str := owner1.EncodeToString()
owner2Str := owner2.EncodeToString()
otherOwnerStr := usertest.OtherID(owner1, owner2).EncodeToString()
check(object.MatchStringEqual, owner1Str, []uint{0, 2})
check(object.MatchStringEqual, owner2Str, []uint{1, 3})
check(object.MatchStringEqual, otherOwnerStr, nil)
check(object.MatchStringNotEqual, owner1Str, []uint{1, 3})
check(object.MatchStringNotEqual, owner2Str, []uint{0, 2})
check(object.MatchStringNotEqual, otherOwnerStr, []uint{0, 1, 2, 3})
for _, m := range []object.SearchMatchType{
object.MatchNotPresent, object.MatchNumGT, object.MatchNumGE, object.MatchNumLT, object.MatchNumLE,
} {
check(m, owner1Str, nil)
check(m, owner2Str, nil)
}
for i := range len(owner1Str) {
check(object.MatchCommonPrefix, owner1Str[:i], []uint{0, 2})
check(object.MatchCommonPrefix, owner2Str[:i], []uint{1, 3})
if owner1Str[:i] != otherOwnerStr[:i] {
check(object.MatchCommonPrefix, otherOwnerStr[:i], nil)
}
}
})
})
}

0 comments on commit f16c1c1

Please sign in to comment.