Skip to content

Commit f16c1c1

Browse files
committed
WIP: unit tests
Signed-off-by: Leonard Lyubich <[email protected]>
1 parent 3bf58af commit f16c1c1

File tree

1 file changed

+114
-2
lines changed

1 file changed

+114
-2
lines changed

pkg/local_object_storage/metabase/metadata_test.go

Lines changed: 114 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"encoding/base64"
66
"math/rand"
77
"slices"
8+
"strconv"
89
"testing"
910

1011
"github.com/nspcc-dev/neofs-sdk-go/checksum"
@@ -15,11 +16,18 @@ import (
1516
oid "github.com/nspcc-dev/neofs-sdk-go/object/id"
1617
oidtest "github.com/nspcc-dev/neofs-sdk-go/object/id/test"
1718
"github.com/nspcc-dev/neofs-sdk-go/user"
19+
usertest "github.com/nspcc-dev/neofs-sdk-go/user/test"
1820
"github.com/nspcc-dev/neofs-sdk-go/version"
1921
"github.com/stretchr/testify/require"
2022
"go.etcd.io/bbolt"
2123
)
2224

25+
func sortObjectIDs(ids []oid.ID) []oid.ID {
26+
s := slices.Clone(ids)
27+
slices.SortFunc(s, func(a, b oid.ID) int { return bytes.Compare(a[:], b[:]) })
28+
return s
29+
}
30+
2331
func assertAttrPrefixed[T string | []byte](t testing.TB, mb *bbolt.Bucket, id oid.ID, prefix byte, attr string, val T) {
2432
k := []byte{prefix}
2533
k = append(k, attr...)
@@ -191,8 +199,7 @@ func TestDB_SearchObjects(t *testing.T) {
191199
require.NoError(t, err, i)
192200
}
193201

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

197204
t.Run("all at once", func(t *testing.T) {
198205
for _, tc := range []struct {
@@ -259,4 +266,109 @@ func TestDB_SearchObjects(t *testing.T) {
259266
require.EqualError(t, err, "view BoltDB: unexpected object key len 31, expected 33")
260267
})
261268
})
269+
t.Run("filters", func(t *testing.T) {
270+
cnr := cidtest.ID()
271+
owner1, owner2 := usertest.ID(), usertest.ID()
272+
const n = 4
273+
var objs [n]object.Object
274+
ids := make([]oid.ID, len(objs))
275+
for i := range objs {
276+
objs[i].SetContainerID(cnr)
277+
objs[i].SetPayloadChecksum(checksumtest.Checksum()) // required to Put
278+
if i%2 == 0 {
279+
objs[i].SetOwnerID(&owner1)
280+
} else {
281+
objs[i].SetOwnerID(&owner2)
282+
}
283+
284+
id := oidtest.ID()
285+
objs[i].SetID(id)
286+
287+
si := strconv.Itoa(i)
288+
objs[i].SetAttributes(
289+
*object.NewAttribute("attr_"+si, "val_"+si),
290+
*object.NewAttribute("attr_common", "val_common"),
291+
)
292+
293+
require.NoError(t, db.Put(&objs[i], nil, nil))
294+
}
295+
296+
ids = sortObjectIDs(ids)
297+
298+
check := func(k string, m object.SearchMatchType, v string, matchInds []uint) {
299+
var fs object.SearchFilters
300+
fs.AddFilter("attr_common", "val_common", object.MatchStringEqual)
301+
fs.AddFilter(k, v, m)
302+
303+
res, cursor, err := db.Search(cnr, fs, []string{"attr_common"}, "", n)
304+
require.NoError(t, err)
305+
require.Empty(t, cursor)
306+
require.Len(t, res, len(matchInds))
307+
for i, ind := range matchInds {
308+
require.Equal(t, ids[ind], res[i].ID)
309+
require.Len(t, res[i].Attributes, 1)
310+
require.Equal(t, "val_common", res[i].Attributes[0])
311+
}
312+
}
313+
314+
t.Run("container", func(t *testing.T) {
315+
// Since container ID is a selection parameter itself, only EQ and PREFIX with
316+
// CID prefix match. For other prefixes, result is always empty, and it can be
317+
// obtained without touching the BoltDB.
318+
check := func(m object.SearchMatchType, v string, match bool) {
319+
var inds []uint
320+
if match {
321+
inds = []uint{0, 1, 2, 3}
322+
}
323+
check(object.FilterContainerID, m, v, inds)
324+
}
325+
326+
cnrStr := cnr.EncodeToString()
327+
otherCnrStr := cidtest.OtherID(cnr).EncodeToString()
328+
check(object.MatchStringEqual, cnrStr, true)
329+
check(object.MatchStringEqual, otherCnrStr, false)
330+
check(object.MatchStringNotEqual, cnrStr, false)
331+
check(object.MatchStringNotEqual, otherCnrStr, true)
332+
for _, m := range []object.SearchMatchType{
333+
object.MatchNotPresent, object.MatchNumGT, object.MatchNumGE, object.MatchNumLT, object.MatchNumLE,
334+
} {
335+
check(m, cnrStr, false)
336+
check(m, otherCnrStr, false)
337+
}
338+
for i := range len(cnrStr) {
339+
check(object.MatchCommonPrefix, cnrStr[:i], true)
340+
if cnrStr[:i] != otherCnrStr[:i] {
341+
check(object.MatchCommonPrefix, otherCnrStr[:i], false)
342+
}
343+
}
344+
// TODO: also check that BoltDB is untouched when on mismatch
345+
})
346+
t.Run("owner", func(t *testing.T) {
347+
check := func(m object.SearchMatchType, v string, matchInds []uint) {
348+
check(object.FilterOwnerID, m, v, matchInds)
349+
}
350+
owner1Str := owner1.EncodeToString()
351+
owner2Str := owner2.EncodeToString()
352+
otherOwnerStr := usertest.OtherID(owner1, owner2).EncodeToString()
353+
check(object.MatchStringEqual, owner1Str, []uint{0, 2})
354+
check(object.MatchStringEqual, owner2Str, []uint{1, 3})
355+
check(object.MatchStringEqual, otherOwnerStr, nil)
356+
check(object.MatchStringNotEqual, owner1Str, []uint{1, 3})
357+
check(object.MatchStringNotEqual, owner2Str, []uint{0, 2})
358+
check(object.MatchStringNotEqual, otherOwnerStr, []uint{0, 1, 2, 3})
359+
for _, m := range []object.SearchMatchType{
360+
object.MatchNotPresent, object.MatchNumGT, object.MatchNumGE, object.MatchNumLT, object.MatchNumLE,
361+
} {
362+
check(m, owner1Str, nil)
363+
check(m, owner2Str, nil)
364+
}
365+
for i := range len(owner1Str) {
366+
check(object.MatchCommonPrefix, owner1Str[:i], []uint{0, 2})
367+
check(object.MatchCommonPrefix, owner2Str[:i], []uint{1, 3})
368+
if owner1Str[:i] != otherOwnerStr[:i] {
369+
check(object.MatchCommonPrefix, otherOwnerStr[:i], nil)
370+
}
371+
}
372+
})
373+
})
262374
}

0 commit comments

Comments
 (0)